diff --git a/.gitignore b/.gitignore index 05bb0a5..ef5aee5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ other/maple-bootloader/cscope.out other/maple-bootloader/build other/maple-bootloader/*~ *.o -tools/src/stm32flash_serial/src/parsers/parsers.a +*.bak +*.1 +platform.local.txt +boards.local.txt diff --git a/README.md b/README.md index 019cb2b..4f6f377 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,43 @@ -Arduino STM32 -============= - -##Notice +Arduino STM32 +============= +## Notice This software is experimental and a work in progress. Under no circumstances should these files be used in relation to any critical system(s). Use of these files is at your own risk. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -##Summary: -This repo contains, the "Hardware" files to support STM32 based boards on Arduino version 1.6.13 or 1.6.12 (some older versions may also work) including [LeafLabs Maple, and Maple mini](http://www.leaflabs.com/about-maple/), and other generic STM32F103 boards +## Summary: +This repo contains the "Hardware" files to support STM32 based boards on Arduino version 1.8.x (some older versions may also work) including [LeafLabs Maple, and Maple mini](http://www.leaflabs.com/about-maple/), and other generic STM32F103 boards. ***PRIMARY SUPPORT FORUM: http://www.stm32duino.com/*** -##Background & Support: -* Based on https://github.com/bobc/maple-asp, which is in turn based on LibMaple by Leaflabs +***We are also on Gitter https://gitter.im/stm32duino/Lobby/*** +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/stm32duino/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Background & Support: +* Based on https://github.com/bobc/maple-asp, which is in turn based on LibMaple by Leaflabs * **Please read the wiki (https://github.com/rogerclarkmelbourne/Arduino_STM32/wiki) for full details** -* See also my blog: http://www.rogerclark.net/stm32f103-and-maple-maple-mini-with-arduino-1-5-x-ide/ -* **NEW: Main support site for using STM32 boards with the Arduino IDE: http://www.stm32duino.com/** +* See also my blog: http://www.rogerclark.net/stm32f103-and-maple-maple-mini-with-arduino-1-5-x-ide/ +* **NEW: Main support site for using STM32 boards with the Arduino IDE: http://www.stm32duino.com/** * Original LeafLabs "Docs:" http://docs.leaflabs.com/docs.leaflabs.com/index.html -**YouTube Videos:** +**YouTube Videos:** * 20141116: [Arduino 1.5.8 IDE with STM32 board](https://www.youtube.com/watch?v=-zwGnytGT8M) * 20150413: [STM32 for Arduino 1.6.2 or newer (update)](https://www.youtube.com/watch?v=TePglhSkghg) * 20150419: [Uploading via USB to Serial to STM32F103 boards](https://www.youtube.com/watch?v=G_RF0a0hrak) -##Additional Links & Info: -* https://www.hackster.io/rayburne/4-dollar-90-mips-32-bit-72-mhz-arm-arduino - -##Purchase info: -###Entry level boards +## Additional Links & Info: +* https://www.hackster.io/rayburne/4-dollar-90-mips-32-bit-72-mhz-arm-arduino +## Purchase info: +### Entry level boards * [Ebay search for "arduino maple"](http://www.ebay.com/sch/i.html?_from=R40&_sacat=0&LH_BIN=1&_nkw=arduino+maple&_sop=15) (currently costs <$5 with shipping) -* [AliExpress search for "leaflabs maple"] (http://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20150607085526&SearchText=leaflabs+maple) +* [AliExpress search for "leaflabs maple"](http://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20150607085526&SearchText=leaflabs+maple) ### Bigger boards (You need to load the stm32duino bootloader) - -Some supplier have this board e.g. - -*[ STM32F103VET ](http://www.ebay.com.au/itm/1PCS-STM32F103VET6-ARM-STM32-Minimum-System-Development-Board-Arduino-M77-/301433302819) - -*[There is also a STM32F103ZET board which also works, however they are not always available. They have been listed as "STM32F103ZET6 Minimum System Development Board ARM STM32 Cortex-m3 M75"] -(http://www.ebay.com.au/itm/1pcs-STM32F103ZET6-Minimum-System-Development-Board-ARM-STM32-Cortex-m3-M75-/291305557264) - +Some suppliers have this board e.g. +* [ STM32F103VET ](http://www.ebay.com.au/itm/1PCS-STM32F103VET6-ARM-STM32-Minimum-System-Development-Board-Arduino-M77-/301433302819) +* [There is also a STM32F103ZET board which also works, however they are not always available. They have been listed as "STM32F103ZET6 Minimum System Development Board ARM STM32 Cortex-m3 M75"](http://www.ebay.com.au/itm/1pcs-STM32F103ZET6-Minimum-System-Development-Board-ARM-STM32-Cortex-m3-M75-/291305557264) diff --git a/STM32F1/boards.txt b/STM32F1/boards.txt index 24202fc..84ce01d 100644 --- a/STM32F1/boards.txt +++ b/STM32F1/boards.txt @@ -4,6 +4,7 @@ menu.device_variant=Variant menu.bootloader_version=Bootloader version menu.upload_method=Upload method menu.cpu_speed=CPU Speed(MHz) +menu.opt=Optimize ############################################################## mapleMini.name=Maple Mini @@ -25,26 +26,56 @@ mapleMini.upload.auto_reset=true mapleMini.menu.bootloader_version.original = Original (17k RAM,108k Flash) mapleMini.menu.bootloader_version.original.build.vect=VECT_TAB_ADDR=0x8005000 mapleMini.menu.bootloader_version.original.build.ldscript=ld/flash.ld -mapleMini.menu.bootloader_version.original.upload.ram.maximum_size=17408 -mapleMini.menu.bootloader_version.original.upload.flash.maximum_size=110592 mapleMini.menu.bootloader_version.original.upload.maximum_size=110592 +mapleMini.menu.bootloader_version.original.upload.maximum_data_size=17408 mapleMini.menu.bootloader_version.original.upload.altID=1 mapleMini.menu.bootloader_version.bootloader20 = Bootloader 2.0 (20k RAM,120k Flash) mapleMini.menu.bootloader_version.bootloader20.build.vect=VECT_TAB_ADDR=0x8002000 mapleMini.menu.bootloader_version.bootloader20.build.ldscript=ld/bootloader_20.ld -mapleMini.menu.bootloader_version.bootloader20.upload.ram.maximum_size=20480 -mapleMini.menu.bootloader_version.bootloader20.upload.flash.maximum_size=122880 mapleMini.menu.bootloader_version.bootloader20.upload.maximum_size=122880 +mapleMini.menu.bootloader_version.bootloader20.upload.maximum_data_size=20480 mapleMini.menu.bootloader_version.bootloader20.upload.altID=2 #-- CPU Clock frequency -mapleMini.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +mapleMini.menu.cpu_speed.speed_72mhz=72MHz (Normal) mapleMini.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L -mapleMini.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +mapleMini.menu.cpu_speed.speed_48mhz=48MHz (Slow - with USB) mapleMini.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L +mapleMini.menu.cpu_speed.speed_128mhz=Overclocked 128MHz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +mapleMini.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +mapleMini.menu.opt.osstd=Smallest (default) +mapleMini.menu.opt.osstd.build.flags.optimize=-Os +mapleMini.menu.opt.osstd.build.flags.ldspecs= +mapleMini.menu.opt.oslto=Smallest Code with LTO +mapleMini.menu.opt.oslto.build.flags.optimize=-Os -flto +mapleMini.menu.opt.oslto.build.flags.ldspecs=-flto +mapleMini.menu.opt.o1std=Fast (-O1) +mapleMini.menu.opt.o1std.build.flags.optimize=-O1 +mapleMini.menu.opt.o1std.build.flags.ldspecs= +mapleMini.menu.opt.o1lto=Fast (-O1) with LTO +mapleMini.menu.opt.o1lto.build.flags.optimize=-O1 -flto +mapleMini.menu.opt.o1lto.build.flags.ldspecs=-flto +mapleMini.menu.opt.o2std=Faster (-O2) +mapleMini.menu.opt.o2std.build.flags.optimize=-O2 +mapleMini.menu.opt.o2std.build.flags.ldspecs= +mapleMini.menu.opt.o2lto=Faster (-O2) with LTO +mapleMini.menu.opt.o2lto.build.flags.optimize=-O2 -flto +mapleMini.menu.opt.o2lto.build.flags.ldspecs=-flto +mapleMini.menu.opt.o3std=Fastest (-O3) +mapleMini.menu.opt.o3std.build.flags.optimize=-O3 +mapleMini.menu.opt.o3std.build.flags.ldspecs= +mapleMini.menu.opt.o3lto=Fastest (-O3) with LTO +mapleMini.menu.opt.o3lto.build.flags.optimize=-O3 -flto +mapleMini.menu.opt.o3lto.build.flags.ldspecs=-flto +mapleMini.menu.opt.ogstd=Debug (-g) +mapleMini.menu.opt.ogstd.build.flags.optimize=-Og +mapleMini.menu.opt.ogstd.build.flags.ldspecs= + ############################################################## maple.name=Maple (Rev 3) @@ -54,10 +85,9 @@ maple.pid.0=0x0004 maple.upload.tool=maple_upload maple.upload.protocol=maple_dfu maple.upload.maximum_size=108000 +maple.upload.maximum_data_size=17000 maple.upload.use_1200bps_touch=false maple.upload.file_type=bin -maple.upload.ram.maximum_size=17000 -maple.upload.flash.maximum_size=108000 maple.upload.usbID=1EAF:0003 maple.upload.altID=1 maple.upload.auto_reset=true @@ -69,6 +99,45 @@ maple.build.ldscript=ld/flash.ld maple.build.variant=maple maple.build.vect=VECT_TAB_ADDR=0x8005000 +#-- CPU Clock frequency +maple.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +maple.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +maple.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +maple.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +maple.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +maple.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +maple.menu.opt.osstd=Smallest (default) +maple.menu.opt.osstd.build.flags.optimize=-Os +maple.menu.opt.osstd.build.flags.ldspecs= +maple.menu.opt.oslto=Smallest Code with LTO +maple.menu.opt.oslto.build.flags.optimize=-Os -flto +maple.menu.opt.oslto.build.flags.ldspecs=-flto +maple.menu.opt.o1std=Fast (-O1) +maple.menu.opt.o1std.build.flags.optimize=-O1 +maple.menu.opt.o1std.build.flags.ldspecs= +maple.menu.opt.o1lto=Fast (-O1) with LTO +maple.menu.opt.o1lto.build.flags.optimize=-O1 -flto +maple.menu.opt.o1lto.build.flags.ldspecs=-flto +maple.menu.opt.o2std=Faster (-O2) +maple.menu.opt.o2std.build.flags.optimize=-O2 +maple.menu.opt.o2std.build.flags.ldspecs= +maple.menu.opt.o2lto=Faster (-O2) with LTO +maple.menu.opt.o2lto.build.flags.optimize=-O2 -flto +maple.menu.opt.o2lto.build.flags.ldspecs=-flto +maple.menu.opt.o3std=Fastest (-O3) +maple.menu.opt.o3std.build.flags.optimize=-O3 +maple.menu.opt.o3std.build.flags.ldspecs= +maple.menu.opt.o3lto=Fastest (-O3) with LTO +maple.menu.opt.o3lto.build.flags.optimize=-O3 -flto +maple.menu.opt.o3lto.build.flags.ldspecs=-flto +maple.menu.opt.ogstd=Debug (-g) +maple.menu.opt.ogstd.build.flags.optimize=-Og +maple.menu.opt.ogstd.build.flags.ldspecs= + ############################################################## mapleRET6.name=Maple (RET6) @@ -85,14 +154,53 @@ mapleRET6.build.vect=VECT_TAB_ADDR=0x8005000 mapleRET6.upload.tool=maple_upload mapleRET6.upload.protocol=maple_dfu mapleRET6.upload.maximum_size=262144 +mapleRET6.upload.maximum_data_size=49152 mapleRET6.upload.use_1200bps_touch=false mapleRET6.upload.file_type=bin -mapleRET6.upload.ram.maximum_size=49152 -mapleRET6.upload.flash.maximum_size=262144 mapleRET6.upload.usbID=1EAF:0003 mapleRET6.upload.altID=1 mapleRET6.upload.auto_reset=true +#-- CPU Clock frequency +mapleRET6.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +mapleRET6.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +mapleRET6.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +mapleRET6.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +mapleRET6.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +mapleRET6.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + + +#-- Optimizations +mapleRET6.menu.opt.osstd=Smallest (default) +mapleRET6.menu.opt.osstd.build.flags.optimize=-Os +mapleRET6.menu.opt.osstd.build.flags.ldspecs= +mapleRET6.menu.opt.oslto=Smallest Code with LTO +mapleRET6.menu.opt.oslto.build.flags.optimize=-Os -flto +mapleRET6.menu.opt.oslto.build.flags.ldspecs=-flto +mapleRET6.menu.opt.o1std=Fast (-O1) +mapleRET6.menu.opt.o1std.build.flags.optimize=-O1 +mapleRET6.menu.opt.o1std.build.flags.ldspecs= +mapleRET6.menu.opt.o1lto=Fast (-O1) with LTO +mapleRET6.menu.opt.o1lto.build.flags.optimize=-O1 -flto +mapleRET6.menu.opt.o1lto.build.flags.ldspecs=-flto +mapleRET6.menu.opt.o2std=Faster (-O2) +mapleRET6.menu.opt.o2std.build.flags.optimize=-O2 +mapleRET6.menu.opt.o2std.build.flags.ldspecs= +mapleRET6.menu.opt.o2lto=Faster (-O2) with LTO +mapleRET6.menu.opt.o2lto.build.flags.optimize=-O2 -flto +mapleRET6.menu.opt.o2lto.build.flags.ldspecs=-flto +mapleRET6.menu.opt.o3std=Fastest (-O3) +mapleRET6.menu.opt.o3std.build.flags.optimize=-O3 +mapleRET6.menu.opt.o3std.build.flags.ldspecs= +mapleRET6.menu.opt.o3lto=Fastest (-O3) with LTO +mapleRET6.menu.opt.o3lto.build.flags.optimize=-O3 -flto +mapleRET6.menu.opt.ogstd=Debug (-g) +mapleRET6.menu.opt.o3lto.build.flags.ldspecs=-flto +mapleRET6.menu.opt.ogstd.build.flags.optimize=-Og +mapleRET6.menu.opt.ogstd.build.flags.ldspecs= + ############################################################## microduino32_flash.name=Microduino Core STM32 to Flash @@ -102,10 +210,9 @@ microduino32_flash.pid.0=0x0004 microduino32_flash.upload.tool=maple_upload microduino32_flash.upload.protocol=maple_dfu microduino32_flash.upload.maximum_size=108000 +microduino32_flash.upload.maximum_data_size=17000 microduino32_flash.upload.use_1200bps_touch=false microduino32_flash.upload.file_type=bin -microduino32_flash.upload.ram.maximum_size=17000 -microduino32_flash.upload.flash.maximum_size=108000 microduino32_flash.upload.usbID=1EAF:0003 microduino32_flash.upload.altID=1 microduino32_flash.upload.auto_reset=true @@ -125,16 +232,54 @@ microduino32_flash.build.error_led_port=GPIOB microduino32_flash.build.error_led_pin=1 microduino32_flash.build.gcc_ver=gcc-arm-none-eabi-4.8.3-2014q1 +#-- CPU Clock frequency +microduino32_flash.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +microduino32_flash.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +microduino32_flash.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +microduino32_flash.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +microduino32_flash.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +microduino32_flash.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +microduino32_flash.menu.opt.osstd=Smallest (default) +microduino32_flash.menu.opt.osstd.build.flags.optimize=-Os +microduino32_flash.menu.opt.osstd.build.flags.ldspecs= +microduino32_flash.menu.opt.oslto=Smallest Code with LTO +microduino32_flash.menu.opt.oslto.build.flags.optimize=-Os -flto +microduino32_flash.menu.opt.oslto.build.flags.ldspecs=-flto +microduino32_flash.menu.opt.o1std=Fast (-O1) +microduino32_flash.menu.opt.o1std.build.flags.optimize=-O1 +microduino32_flash.menu.opt.o1std.build.flags.ldspecs= +microduino32_flash.menu.opt.o1lto=Fast (-O1) with LTO +microduino32_flash.menu.opt.o1lto.build.flags.optimize=-O1 -flto +microduino32_flash.menu.opt.o1lto.build.flags.ldspecs=-flto +microduino32_flash.menu.opt.o2std=Faster (-O2) +microduino32_flash.menu.opt.o2std.build.flags.optimize=-O2 +microduino32_flash.menu.opt.o2std.build.flags.ldspecs= +microduino32_flash.menu.opt.o2lto=Faster (-O2) with LTO +microduino32_flash.menu.opt.o2lto.build.flags.optimize=-O2 -flto +microduino32_flash.menu.opt.o2lto.build.flags.ldspecs=-flto +microduino32_flash.menu.opt.o3std=Fastest (-O3) +microduino32_flash.menu.opt.o3std.build.flags.optimize=-O3 +microduino32_flash.menu.opt.o3std.build.flags.ldspecs= +microduino32_flash.menu.opt.o3lto=Fastest (-O3) with LTO +microduino32_flash.menu.opt.o3lto.build.flags.optimize=-O3 -flto +microduino32_flash.menu.opt.ogstd=Debug (-g) +microduino32_flash.menu.opt.o3lto.build.flags.ldspecs=-flto +microduino32_flash.menu.opt.ogstd.build.flags.optimize=-Og +microduino32_flash.menu.opt.ogstd.build.flags.ldspecs= + ############################################################## nucleo_f103rb.name=STM Nucleo F103RB (STLink) nucleo_f103rb.upload.tool=stlink_upload nucleo_f103rb.upload.protocol=maple_dfu nucleo_f103rb.upload.maximum_size=108000 +nucleo_f103rb.upload.maximum_data_size=17000 nucleo_f103rb.upload.use_1200bps_touch=false nucleo_f103rb.upload.file_type=bin -nucleo_f103rb.upload.ram.maximum_size=17000 -nucleo_f103rb.upload.flash.maximum_size=108000 nucleo_f103rb.upload.params.quiet=no nucleo_f103rb.upload.usbID=1EAF:0003 @@ -147,7 +292,6 @@ nucleo_f103rb.build.core=maple nucleo_f103rb.build.ldscript=ld/jtag.ld nucleo_f103rb.build.variant=nucleo_f103rb nucleo_f103rb.build.variant_system_lib=libmaple.a -nucleo_f103rb.build.vect=VECT_TAB_FLASH nucleo_f103rb.build.density=STM32_MEDIUM_DENSITY nucleo_f103rb.build.error_led_port=GPIOB nucleo_f103rb.build.error_led_pin=1 @@ -164,6 +308,35 @@ nucleo_f103rb.menu.device_variant.NucleoF103_HSE=Nucleo F103 @ 72 MHz w/ crystal nucleo_f103rb.menu.device_variant.NucleoF103_HSE.build.f_cpu=72000000L nucleo_f103rb.menu.device_variant.NucleoF103_HSE.build.extra_flags=-DNUCLEO_HSE_CRYSTAL -DMCU_STM32F103RB -mthumb -march=armv7-m -D__STM32F1__ +#-- Optimizations +nucleo_f103rb.menu.opt.osstd=Smallest (default) +nucleo_f103rb.menu.opt.osstd.build.flags.optimize=-Os +nucleo_f103rb.menu.opt.osstd.build.flags.ldspecs= +nucleo_f103rb.menu.opt.oslto=Smallest Code with LTO +nucleo_f103rb.menu.opt.oslto.build.flags.optimize=-Os -flto +nucleo_f103rb.menu.opt.oslto.build.flags.ldspecs=-flto +nucleo_f103rb.menu.opt.o1std=Fast (-O1) +nucleo_f103rb.menu.opt.o1std.build.flags.optimize=-O1 +nucleo_f103rb.menu.opt.o1std.build.flags.ldspecs= +nucleo_f103rb.menu.opt.o1lto=Fast (-O1) with LTO +nucleo_f103rb.menu.opt.o1lto.build.flags.optimize=-O1 -flto +nucleo_f103rb.menu.opt.o1lto.build.flags.ldspecs=-flto +nucleo_f103rb.menu.opt.o2std=Faster (-O2) +nucleo_f103rb.menu.opt.o2std.build.flags.optimize=-O2 +nucleo_f103rb.menu.opt.o2std.build.flags.ldspecs= +nucleo_f103rb.menu.opt.o2lto=Faster (-O2) with LTO +nucleo_f103rb.menu.opt.o2lto.build.flags.optimize=-O2 -flto +nucleo_f103rb.menu.opt.o2lto.build.flags.ldspecs=-flto +nucleo_f103rb.menu.opt.o3std=Fastest (-O3) +nucleo_f103rb.menu.opt.o3std.build.flags.optimize=-O3 +nucleo_f103rb.menu.opt.o3std.build.flags.ldspecs= +nucleo_f103rb.menu.opt.o3lto=Fastest (-O3) with LTO +nucleo_f103rb.menu.opt.o3lto.build.flags.optimize=-O3 -flto +nucleo_f103rb.menu.opt.ogstd=Debug (-g) +nucleo_f103rb.menu.opt.o3lto.build.flags.ldspecs=-flto +nucleo_f103rb.menu.opt.ogstd.build.flags.optimize=-Og +nucleo_f103rb.menu.opt.ogstd.build.flags.ldspecs= + ###################### Generic STM32F103C ######################################## genericSTM32F103C.name=Generic STM32F103C series @@ -173,32 +346,34 @@ genericSTM32F103C.build.variant=generic_stm32f103c genericSTM32F103C.build.vect=VECT_TAB_ADDR=0x8000000 genericSTM32F103C.build.core=maple genericSTM32F103C.build.board=GENERIC_STM32F103C +genericSTM32F103C.build.error_led_port=GPIOC +genericSTM32F103C.build.error_led_pin=13 genericSTM32F103C.upload.use_1200bps_touch=false genericSTM32F103C.upload.file_type=bin genericSTM32F103C.upload.auto_reset=true +genericSTM32F103C.upload.tool=maple_upload +genericSTM32F103C.upload.protocol=maple_dfu ## STM32F103C8 ------------------------- genericSTM32F103C.menu.device_variant.STM32F103C8=STM32F103C8 (20k RAM. 64k Flash) genericSTM32F103C.menu.device_variant.STM32F103C8.build.cpu_flags=-DMCU_STM32F103C8 genericSTM32F103C.menu.device_variant.STM32F103C8.build.ldscript=ld/jtag_c8.ld genericSTM32F103C.menu.device_variant.STM32F103C8.upload.maximum_size=65536 -genericSTM32F103C.menu.device_variant.STM32F103C8.upload.ram.maximum_size=20480 -genericSTM32F103C.menu.device_variant.STM32F103C8.upload.flash.maximum_size=65536 +genericSTM32F103C.menu.device_variant.STM32F103C8.upload.maximum_data_size=20480 ## STM32F103CB ------------------------- genericSTM32F103C.menu.device_variant.STM32F103CB=STM32F103CB (20k RAM. 128k Flash) genericSTM32F103C.menu.device_variant.STM32F103CB.build.cpu_flags=-DMCU_STM32F103CB genericSTM32F103C.menu.device_variant.STM32F103CB.build.ldscript=ld/jtag.ld genericSTM32F103C.menu.device_variant.STM32F103CB.upload.maximum_size=131072 -genericSTM32F103C.menu.device_variant.STM32F103CB.upload.ram.maximum_size=20480 -genericSTM32F103C.menu.device_variant.STM32F103CB.upload.flash.maximum_size=131072 +genericSTM32F103C.menu.device_variant.STM32F103CB.upload.maximum_data_size=20480 #---------------------------- UPLOAD METHODS --------------------------- genericSTM32F103C.menu.upload_method.DFUUploadMethod=STM32duino bootloader genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload -genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 +genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 @@ -219,7 +394,6 @@ genericSTM32F103C.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp genericSTM32F103C.menu.upload_method.BMPMethod.upload.tool=bmp_upload genericSTM32F103C.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG - genericSTM32F103C.menu.upload_method.jlinkMethod=JLink genericSTM32F103C.menu.upload_method.jlinkMethod.upload.protocol=jlink genericSTM32F103C.menu.upload_method.jlinkMethod.upload.tool=jlink_upload @@ -232,6 +406,38 @@ genericSTM32F103C.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L genericSTM32F103C.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) genericSTM32F103C.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L +genericSTM32F103C.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +genericSTM32F103C.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +genericSTM32F103C.menu.opt.osstd=Smallest (default) +genericSTM32F103C.menu.opt.osstd.build.flags.optimize=-Os +genericSTM32F103C.menu.opt.osstd.build.flags.ldspecs= +genericSTM32F103C.menu.opt.oslto=Smallest Code with LTO +genericSTM32F103C.menu.opt.oslto.build.flags.optimize=-Os -flto +genericSTM32F103C.menu.opt.oslto.build.flags.ldspecs=-flto +genericSTM32F103C.menu.opt.o1std=Fast (-O1) +genericSTM32F103C.menu.opt.o1std.build.flags.optimize=-O1 +genericSTM32F103C.menu.opt.o1std.build.flags.ldspecs= +genericSTM32F103C.menu.opt.o1lto=Fast (-O1) with LTO +genericSTM32F103C.menu.opt.o1lto.build.flags.optimize=-O1 -flto +genericSTM32F103C.menu.opt.o1lto.build.flags.ldspecs=-flto +genericSTM32F103C.menu.opt.o2std=Faster (-O2) +genericSTM32F103C.menu.opt.o2std.build.flags.optimize=-O2 +genericSTM32F103C.menu.opt.o2std.build.flags.ldspecs= +genericSTM32F103C.menu.opt.o2lto=Faster (-O2) with LTO +genericSTM32F103C.menu.opt.o2lto.build.flags.optimize=-O2 -flto +genericSTM32F103C.menu.opt.o2lto.build.flags.ldspecs=-flto +genericSTM32F103C.menu.opt.o3std=Fastest (-O3) +genericSTM32F103C.menu.opt.o3std.build.flags.optimize=-O3 +genericSTM32F103C.menu.opt.o3std.build.flags.ldspecs= +genericSTM32F103C.menu.opt.o3lto=Fastest (-O3) with LTO +genericSTM32F103C.menu.opt.o3lto.build.flags.optimize=-O3 -flto +genericSTM32F103C.menu.opt.ogstd=Debug (-g) +genericSTM32F103C.menu.opt.o3lto.build.flags.ldspecs=-flto +genericSTM32F103C.menu.opt.ogstd.build.flags.optimize=-Og +genericSTM32F103C.menu.opt.ogstd.build.flags.ldspecs= + ########################### Generic STM32F103R ########################### genericSTM32F103R.name=Generic STM32F103R series @@ -244,27 +450,28 @@ genericSTM32F103R.build.board=GENERIC_STM32F103R genericSTM32F103R.upload.use_1200bps_touch=false genericSTM32F103R.upload.file_type=bin genericSTM32F103R.upload.auto_reset=true +genericSTM32F103R.upload.tool=maple_upload +genericSTM32F103R.upload.protocol=maple_dfu genericSTM32F103R.menu.device_variant.STM32F103R8=STM32F103R8 (20k RAM. 64k Flash) genericSTM32F103R.menu.device_variant.STM32F103R8.build.variant=generic_stm32f103r8 genericSTM32F103R.menu.device_variant.STM32F103R8.build.cpu_flags=-DMCU_STM32F103R8 genericSTM32F103R.menu.device_variant.STM32F103R8.upload.maximum_size=65536 -genericSTM32F103R.menu.device_variant.STM32F103R8.upload.ram.maximum_size=20480 -genericSTM32F103R.menu.device_variant.STM32F103R8.upload.flash.maximum_size=65536 +genericSTM32F103R.menu.device_variant.STM32F103R8.upload.maximum_data_size=20480 genericSTM32F103R.menu.device_variant.STM32F103R8.build.ldscript=ld/stm32f103r8.ld genericSTM32F103R.menu.device_variant.STM32F103RB=STM32F103RB (20k RAM. 128k Flash) genericSTM32F103R.menu.device_variant.STM32F103RB.build.variant=generic_stm32f103r8 genericSTM32F103R.menu.device_variant.STM32F103RB.build.cpu_flags=-DMCU_STM32F103RB genericSTM32F103R.menu.device_variant.STM32F103RB.upload.maximum_size=131072 -genericSTM32F103R.menu.device_variant.STM32F103RB.upload.ram.maximum_size=20480 -genericSTM32F103R.menu.device_variant.STM32F103RB.upload.flash.maximum_size=131072 +genericSTM32F103R.menu.device_variant.STM32F103RB.upload.maximum_data_size=20480 genericSTM32F103R.menu.device_variant.STM32F103RB.build.ldscript=ld/stm32f103rb.ld genericSTM32F103R.menu.device_variant.STM32F103RC=STM32F103RC (48k RAM. 256k Flash) genericSTM32F103R.menu.device_variant.STM32F103RC.build.variant=generic_stm32f103r genericSTM32F103R.menu.device_variant.STM32F103RC.build.cpu_flags=-DMCU_STM32F103RC genericSTM32F103R.menu.device_variant.STM32F103RC.upload.maximum_size=262144 +genericSTM32F103R.menu.device_variant.STM32F103RC.upload.maximum_data_size=49152 genericSTM32F103R.menu.device_variant.STM32F103RC.upload.ram.maximum_size=49152 genericSTM32F103R.menu.device_variant.STM32F103RC.upload.flash.maximum_size=262144 genericSTM32F103R.menu.device_variant.STM32F103RC.build.ldscript=ld/stm32f103rc.ld @@ -273,8 +480,7 @@ genericSTM32F103R.menu.device_variant.STM32F103RE=STM32F103RE (64k RAM. 512k Fla genericSTM32F103R.menu.device_variant.STM32F103RE.build.variant=generic_stm32f103r genericSTM32F103R.menu.device_variant.STM32F103RE.build.cpu_flags=-DMCU_STM32F103RE genericSTM32F103R.menu.device_variant.STM32F103RE.upload.maximum_size=524288 -genericSTM32F103R.menu.device_variant.STM32F103RE.upload.ram.maximum_size=65536 -genericSTM32F103R.menu.device_variant.STM32F103RE.upload.flash.maximum_size=524288 +genericSTM32F103R.menu.device_variant.STM32F103RE.upload.maximum_data_size=65536 genericSTM32F103R.menu.device_variant.STM32F103RE.build.ldscript=ld/stm32f103re.ld #---------------------------- UPLOAD METHODS --------------------------- @@ -282,7 +488,7 @@ genericSTM32F103R.menu.device_variant.STM32F103RE.build.ldscript=ld/stm32f103re. genericSTM32F103R.menu.upload_method.DFUUploadMethod=STM32duino bootloader genericSTM32F103R.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu genericSTM32F103R.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload -genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 +genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader.ld genericSTM32F103R.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 @@ -303,6 +509,46 @@ genericSTM32F103R.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp genericSTM32F103R.menu.upload_method.BMPMethod.upload.tool=bmp_upload genericSTM32F103R.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG +#-- CPU Clock frequency +genericSTM32F103R.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +genericSTM32F103R.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +genericSTM32F103R.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +genericSTM32F103R.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +genericSTM32F103R.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +genericSTM32F103R.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + + +#-- Optimizations +genericSTM32F103R.menu.opt.osstd=Smallest (default) +genericSTM32F103R.menu.opt.osstd.build.flags.optimize=-Os +genericSTM32F103R.menu.opt.osstd.build.flags.ldspecs= +genericSTM32F103R.menu.opt.oslto=Smallest Code with LTO +genericSTM32F103R.menu.opt.oslto.build.flags.optimize=-Os -flto +genericSTM32F103R.menu.opt.oslto.build.flags.ldspecs=-flto +genericSTM32F103R.menu.opt.o1std=Fast (-O1) +genericSTM32F103R.menu.opt.o1std.build.flags.optimize=-O1 +genericSTM32F103R.menu.opt.o1std.build.flags.ldspecs= +genericSTM32F103R.menu.opt.o1lto=Fast (-O1) with LTO +genericSTM32F103R.menu.opt.o1lto.build.flags.optimize=-O1 -flto +genericSTM32F103R.menu.opt.o1lto.build.flags.ldspecs=-flto +genericSTM32F103R.menu.opt.o2std=Faster (-O2) +genericSTM32F103R.menu.opt.o2std.build.flags.optimize=-O2 +genericSTM32F103R.menu.opt.o2std.build.flags.ldspecs= +genericSTM32F103R.menu.opt.o2lto=Faster (-O2) with LTO +genericSTM32F103R.menu.opt.o2lto.build.flags.optimize=-O2 -flto +genericSTM32F103R.menu.opt.o2lto.build.flags.ldspecs=-flto +genericSTM32F103R.menu.opt.o3std=Fastest (-O3) +genericSTM32F103R.menu.opt.o3std.build.flags.optimize=-O3 +genericSTM32F103R.menu.opt.o3std.build.flags.ldspecs= +genericSTM32F103R.menu.opt.o3lto=Fastest (-O3) with LTO +genericSTM32F103R.menu.opt.o3lto.build.flags.optimize=-O3 -flto +genericSTM32F103R.menu.opt.ogstd=Debug (-g) +genericSTM32F103R.menu.opt.o3lto.build.flags.ldspecs=-flto +genericSTM32F103R.menu.opt.ogstd.build.flags.optimize=-Og +genericSTM32F103R.menu.opt.ogstd.build.flags.ldspecs= + ###################### Generic STM32F103T ######################################## genericSTM32F103T.name=Generic STM32F103T series @@ -315,29 +561,29 @@ genericSTM32F103T.build.board=GENERIC_STM32F103T genericSTM32F103T.upload.use_1200bps_touch=false genericSTM32F103T.upload.file_type=bin genericSTM32F103T.upload.auto_reset=true +genericSTM32F103T.upload.tool=maple_upload +genericSTM32F103T.upload.protocol=maple_dfu ## STM32F103T8 ------------------------- genericSTM32F103T.menu.device_variant.STM32F103T8=STM32F103T8 (20k RAM. 64k Flash) genericSTM32F103T.menu.device_variant.STM32F103T8.build.cpu_flags=-DMCU_STM32F103T8 genericSTM32F103T.menu.device_variant.STM32F103T8.build.ldscript=ld/jtag_t8.ld genericSTM32F103T.menu.device_variant.STM32F103T8.upload.maximum_size=65536 -genericSTM32F103T.menu.device_variant.STM32F103T8.upload.ram.maximum_size=20480 -genericSTM32F103T.menu.device_variant.STM32F103T8.upload.flash.maximum_size=65536 +genericSTM32F103T.menu.device_variant.STM32F103T8.upload.maximum_data_size=20480 ## STM32F103TB ------------------------- genericSTM32F103T.menu.device_variant.STM32F103TB=STM32F103TB (20k RAM. 128k Flash) genericSTM32F103T.menu.device_variant.STM32F103TB.build.cpu_flags=-DMCU_STM32F103TB genericSTM32F103T.menu.device_variant.STM32F103TB.build.ldscript=ld/jtag.ld genericSTM32F103T.menu.device_variant.STM32F103TB.upload.maximum_size=131072 -genericSTM32F103T.menu.device_variant.STM32F103TB.upload.ram.maximum_size=20480 -genericSTM32F103T.menu.device_variant.STM32F103TB.upload.flash.maximum_size=131072 +genericSTM32F103T.menu.device_variant.STM32F103TB.upload.maximum_data_size=20480 #---------------------------- UPLOAD METHODS --------------------------- genericSTM32F103T.menu.upload_method.DFUUploadMethod=STM32duino bootloader genericSTM32F103T.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu genericSTM32F103T.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload -genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 +genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld genericSTM32F103T.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 @@ -358,41 +604,89 @@ genericSTM32F103T.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp genericSTM32F103T.menu.upload_method.BMPMethod.upload.tool=bmp_upload genericSTM32F103T.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG +#-- CPU Clock frequency +genericSTM32F103T.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +genericSTM32F103T.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +genericSTM32F103T.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +genericSTM32F103T.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +genericSTM32F103T.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +genericSTM32F103T.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +genericSTM32F103T.menu.opt.osstd=Smallest (default) +genericSTM32F103T.menu.opt.osstd.build.flags.optimize=-Os +genericSTM32F103T.menu.opt.osstd.build.flags.ldspecs= +genericSTM32F103T.menu.opt.oslto=Smallest Code with LTO +genericSTM32F103T.menu.opt.oslto.build.flags.optimize=-Os -flto +genericSTM32F103T.menu.opt.oslto.build.flags.ldspecs=-flto +genericSTM32F103T.menu.opt.o1std=Fast (-O1) +genericSTM32F103T.menu.opt.o1std.build.flags.optimize=-O1 +genericSTM32F103T.menu.opt.o1std.build.flags.ldspecs= +genericSTM32F103T.menu.opt.o1lto=Fast (-O1) with LTO +genericSTM32F103T.menu.opt.o1lto.build.flags.optimize=-O1 -flto +genericSTM32F103T.menu.opt.o1lto.build.flags.ldspecs=-flto +genericSTM32F103T.menu.opt.o2std=Faster (-O2) +genericSTM32F103T.menu.opt.o2std.build.flags.optimize=-O2 +genericSTM32F103T.menu.opt.o2std.build.flags.ldspecs= +genericSTM32F103T.menu.opt.o2lto=Faster (-O2) with LTO +genericSTM32F103T.menu.opt.o2lto.build.flags.optimize=-O2 -flto +genericSTM32F103T.menu.opt.o2lto.build.flags.ldspecs=-flto +genericSTM32F103T.menu.opt.o3std=Fastest (-O3) +genericSTM32F103T.menu.opt.o3std.build.flags.optimize=-O3 +genericSTM32F103T.menu.opt.o3std.build.flags.ldspecs= +genericSTM32F103T.menu.opt.o3lto=Fastest (-O3) with LTO +genericSTM32F103T.menu.opt.o3lto.build.flags.optimize=-O3 -flto +genericSTM32F103T.menu.opt.ogstd=Debug (-g) +genericSTM32F103T.menu.opt.o3lto.build.flags.ldspecs=-flto +genericSTM32F103T.menu.opt.ogstd.build.flags.optimize=-Og +genericSTM32F103T.menu.opt.ogstd.build.flags.ldspecs= + ########################### Generic STM32F103V ########################### genericSTM32F103V.name=Generic STM32F103V series genericSTM32F103V.vid.0=0x1EAF genericSTM32F103V.pid.0=0x0004 -genericSTM32F103V.build.variant=generic_stm32f103v +#genericSTM32F103V.build.variant=generic_stm32f103v genericSTM32F103V.build.vect=VECT_TAB_ADDR=0x8000000 genericSTM32F103V.build.core=maple genericSTM32F103V.build.board=GENERIC_STM32F103V genericSTM32F103V.upload.use_1200bps_touch=false genericSTM32F103V.upload.file_type=bin genericSTM32F103V.upload.auto_reset=true +genericSTM32F103V.upload.tool=maple_upload +genericSTM32F103V.upload.protocol=maple_dfu genericSTM32F103V.build.error_led_port=GPIOE genericSTM32F103V.build.error_led_pin=6 +genericSTM32F103V.menu.device_variant.STM32F103VB=STM32F103VB +genericSTM32F103V.menu.device_variant.STM32F103VB.build.variant=generic_stm32f103vb +genericSTM32F103V.menu.device_variant.STM32F103VB.build.cpu_flags=-DMCU_STM32F103VB +genericSTM32F103V.menu.device_variant.STM32F103VB.upload.maximum_size=131072 +genericSTM32F103V.menu.device_variant.STM32F103VB.upload.maximum_data_size=20480 +genericSTM32F103V.menu.device_variant.STM32F103VB.build.ldscript=ld/stm32f103vb.ld + genericSTM32F103V.menu.device_variant.STM32F103VC=STM32F103VC +genericSTM32F103V.menu.device_variant.STM32F103VC.build.variant=generic_stm32f103v genericSTM32F103V.menu.device_variant.STM32F103VC.build.cpu_flags=-DMCU_STM32F103VC genericSTM32F103V.menu.device_variant.STM32F103VC.upload.maximum_size=262144 -genericSTM32F103V.menu.device_variant.STM32F103VC.upload.ram.maximum_size=49152 -genericSTM32F103V.menu.device_variant.STM32F103VC.upload.flash.maximum_size=262144 +genericSTM32F103V.menu.device_variant.STM32F103VC.upload.maximum_data_size=49152 genericSTM32F103V.menu.device_variant.STM32F103VC.build.ldscript=ld/stm32f103vc.ld genericSTM32F103V.menu.device_variant.STM32F103VD=STM32F103VD +genericSTM32F103V.menu.device_variant.STM32F103VD.build.variant=generic_stm32f103v genericSTM32F103V.menu.device_variant.STM32F103VD.build.cpu_flags=-DMCU_STM32F103VD genericSTM32F103V.menu.device_variant.STM32F103VD.upload.maximum_size=393216 -genericSTM32F103V.menu.device_variant.STM32F103VD.upload.ram.maximum_size=65536 -genericSTM32F103V.menu.device_variant.STM32F103VD.upload.flash.maximum_size=393216 +genericSTM32F103V.menu.device_variant.STM32F103VD.upload.maximum_data_size=65536 genericSTM32F103V.menu.device_variant.STM32F103VD.build.ldscript=ld/stm32f103vd.ld genericSTM32F103V.menu.device_variant.STM32F103VE=STM32F103VE +genericSTM32F103V.menu.device_variant.STM32F103VE.build.variant=generic_stm32f103v genericSTM32F103V.menu.device_variant.STM32F103VE.build.cpu_flags=-DMCU_STM32F103VE genericSTM32F103V.menu.device_variant.STM32F103VE.upload.maximum_size=524288 -genericSTM32F103V.menu.device_variant.STM32F103VE.upload.ram.maximum_size=65536 -genericSTM32F103V.menu.device_variant.STM32F103VE.upload.flash.maximum_size=524288 +genericSTM32F103V.menu.device_variant.STM32F103VE.upload.maximum_data_size=65536 genericSTM32F103V.menu.device_variant.STM32F103VE.build.ldscript=ld/stm32f103ve.ld #---------------------------- UPLOAD METHODS --------------------------- @@ -400,7 +694,7 @@ genericSTM32F103V.menu.device_variant.STM32F103VE.build.ldscript=ld/stm32f103ve. genericSTM32F103V.menu.upload_method.DFUUploadMethod=STM32duino bootloader genericSTM32F103V.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu genericSTM32F103V.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload -genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 +genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.ldscript=ld/stm32f103veDFU.ld genericSTM32F103V.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 @@ -421,6 +715,45 @@ genericSTM32F103V.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp genericSTM32F103V.menu.upload_method.BMPMethod.upload.tool=bmp_upload genericSTM32F103V.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG +#-- CPU Clock frequency +genericSTM32F103V.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +genericSTM32F103V.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +genericSTM32F103V.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +genericSTM32F103V.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +genericSTM32F103V.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +genericSTM32F103V.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +genericSTM32F103V.menu.opt.osstd=Smallest (default) +genericSTM32F103V.menu.opt.osstd.build.flags.optimize=-Os +genericSTM32F103V.menu.opt.osstd.build.flags.ldspecs= +genericSTM32F103V.menu.opt.oslto=Smallest Code with LTO +genericSTM32F103V.menu.opt.oslto.build.flags.optimize=-Os -flto +genericSTM32F103V.menu.opt.oslto.build.flags.ldspecs=-flto +genericSTM32F103V.menu.opt.o1std=Fast (-O1) +genericSTM32F103V.menu.opt.o1std.build.flags.optimize=-O1 +genericSTM32F103V.menu.opt.o1std.build.flags.ldspecs= +genericSTM32F103V.menu.opt.o1lto=Fast (-O1) with LTO +genericSTM32F103V.menu.opt.o1lto.build.flags.optimize=-O1 -flto +genericSTM32F103V.menu.opt.o1lto.build.flags.ldspecs=-flto +genericSTM32F103V.menu.opt.o2std=Faster (-O2) +genericSTM32F103V.menu.opt.o2std.build.flags.optimize=-O2 +genericSTM32F103V.menu.opt.o2std.build.flags.ldspecs= +genericSTM32F103V.menu.opt.o2lto=Faster (-O2) with LTO +genericSTM32F103V.menu.opt.o2lto.build.flags.optimize=-O2 -flto +genericSTM32F103V.menu.opt.o2lto.build.flags.ldspecs=-flto +genericSTM32F103V.menu.opt.o3std=Fastest (-O3) +genericSTM32F103V.menu.opt.o3std.build.flags.optimize=-O3 +genericSTM32F103V.menu.opt.o3std.build.flags.ldspecs= +genericSTM32F103V.menu.opt.o3lto=Fastest (-O3) with LTO +genericSTM32F103V.menu.opt.o3lto.build.flags.optimize=-O3 -flto +genericSTM32F103V.menu.opt.ogstd=Debug (-g) +genericSTM32F103V.menu.opt.o3lto.build.flags.ldspecs=-flto +genericSTM32F103V.menu.opt.ogstd.build.flags.optimize=-Og +genericSTM32F103V.menu.opt.ogstd.build.flags.ldspecs= + ########################### Generic STM32F103Z ########################### genericSTM32F103Z.name=Generic STM32F103Z series @@ -433,26 +766,25 @@ genericSTM32F103Z.build.board=GENERIC_STM32F103Z genericSTM32F103Z.upload.use_1200bps_touch=false genericSTM32F103Z.upload.file_type=bin genericSTM32F103Z.upload.auto_reset=true +genericSTM32F103Z.upload.tool=maple_upload +genericSTM32F103Z.upload.protocol=maple_dfu genericSTM32F103Z.menu.device_variant.STM32F103ZC=STM32F103ZC genericSTM32F103Z.menu.device_variant.STM32F103ZC.build.cpu_flags=-DMCU_STM32F103ZC genericSTM32F103Z.menu.device_variant.STM32F103ZC.upload.maximum_size=262144 -genericSTM32F103Z.menu.device_variant.STM32F103ZC.upload.ram.maximum_size=49152 -genericSTM32F103Z.menu.device_variant.STM32F103ZC.upload.flash.maximum_size=262144 +genericSTM32F103Z.menu.device_variant.STM32F103ZC.upload.maximum_data_size=49152 genericSTM32F103Z.menu.device_variant.STM32F103ZC.build.ldscript=ld/stm32f103zc.ld genericSTM32F103Z.menu.device_variant.STM32F103ZD=STM32F103ZD genericSTM32F103Z.menu.device_variant.STM32F103ZD.build.cpu_flags=-DMCU_STM32F103ZD genericSTM32F103Z.menu.device_variant.STM32F103ZD.upload.maximum_size=393216 -genericSTM32F103Z.menu.device_variant.STM32F103ZD.upload.ram.maximum_size=65536 -genericSTM32F103Z.menu.device_variant.STM32F103ZD.upload.flash.maximum_size=393216 +genericSTM32F103Z.menu.device_variant.STM32F103ZD.upload.maximum_data_size=65536 genericSTM32F103Z.menu.device_variant.STM32F103ZD.build.ldscript=ld/stm32f103zd.ld genericSTM32F103Z.menu.device_variant.STM32F103ZE=STM32F103ZE genericSTM32F103Z.menu.device_variant.STM32F103ZE.build.cpu_flags=-DMCU_STM32F103ZE genericSTM32F103Z.menu.device_variant.STM32F103ZE.upload.maximum_size=524288 -genericSTM32F103Z.menu.device_variant.STM32F103ZE.upload.ram.maximum_size=65536 -genericSTM32F103Z.menu.device_variant.STM32F103ZE.upload.flash.maximum_size=524288 +genericSTM32F103Z.menu.device_variant.STM32F103ZE.upload.maximum_data_size=65536 genericSTM32F103Z.menu.device_variant.STM32F103ZE.build.ldscript=ld/stm32f103ze.ld #---------------------------- UPLOAD METHODS --------------------------- @@ -460,7 +792,7 @@ genericSTM32F103Z.menu.device_variant.STM32F103ZE.build.ldscript=ld/stm32f103ze. genericSTM32F103Z.menu.upload_method.DFUUploadMethod=STM32duino bootloader genericSTM32F103Z.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu genericSTM32F103Z.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload -genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 +genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.ldscript=ld/stm32f103z_dfu.ld genericSTM32F103Z.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 @@ -481,6 +813,45 @@ genericSTM32F103Z.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp genericSTM32F103Z.menu.upload_method.BMPMethod.upload.tool=bmp_upload genericSTM32F103Z.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG +#-- CPU Clock frequency +genericSTM32F103Z.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +genericSTM32F103Z.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +genericSTM32F103Z.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +genericSTM32F103Z.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +genericSTM32F103Z.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +genericSTM32F103Z.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +genericSTM32F103Z.menu.opt.osstd=Smallest (default) +genericSTM32F103Z.menu.opt.osstd.build.flags.optimize=-Os +genericSTM32F103Z.menu.opt.osstd.build.flags.ldspecs= +genericSTM32F103Z.menu.opt.oslto=Smallest Code with LTO +genericSTM32F103Z.menu.opt.oslto.build.flags.optimize=-Os -flto +genericSTM32F103Z.menu.opt.oslto.build.flags.ldspecs=-flto +genericSTM32F103Z.menu.opt.o1std=Fast (-O1) +genericSTM32F103Z.menu.opt.o1std.build.flags.optimize=-O1 +genericSTM32F103Z.menu.opt.o1std.build.flags.ldspecs= +genericSTM32F103Z.menu.opt.o1lto=Fast (-O1) with LTO +genericSTM32F103Z.menu.opt.o1lto.build.flags.optimize=-O1 -flto +genericSTM32F103Z.menu.opt.o1lto.build.flags.ldspecs=-flto +genericSTM32F103Z.menu.opt.o2std=Faster (-O2) +genericSTM32F103Z.menu.opt.o2std.build.flags.optimize=-O2 +genericSTM32F103Z.menu.opt.o2std.build.flags.ldspecs= +genericSTM32F103Z.menu.opt.o2lto=Faster (-O2) with LTO +genericSTM32F103Z.menu.opt.o2lto.build.flags.optimize=-O2 -flto +genericSTM32F103Z.menu.opt.o2lto.build.flags.ldspecs=-flto +genericSTM32F103Z.menu.opt.o3std=Fastest (-O3) +genericSTM32F103Z.menu.opt.o3std.build.flags.optimize=-O3 +genericSTM32F103Z.menu.opt.o3std.build.flags.ldspecs= +genericSTM32F103Z.menu.opt.o3lto=Fastest (-O3) with LTO +genericSTM32F103Z.menu.opt.o3lto.build.flags.optimize=-O3 -flto +genericSTM32F103Z.menu.opt.ogstd=Debug (-g) +genericSTM32F103Z.menu.opt.o3lto.build.flags.ldspecs=-flto +genericSTM32F103Z.menu.opt.ogstd.build.flags.optimize=-Og +genericSTM32F103Z.menu.opt.ogstd.build.flags.ldspecs= + ###################### HYTiny STM32F103T ######################################## hytiny-stm32f103t.name=HYTiny STM32F103TB @@ -498,9 +869,7 @@ hytiny-stm32f103t.upload.auto_reset=true hytiny-stm32f103t.build.cpu_flags=-DMCU_STM32F103CB hytiny-stm32f103t.build.ldscript=ld/jtag.ld hytiny-stm32f103t.upload.maximum_size=131072 -hytiny-stm32f103t.upload.ram.maximum_size=20480 -hytiny-stm32f103t.upload.flash.maximum_size=131072 - +hytiny-stm32f103t.upload.maximum_data_size=20480 #---------------------------- UPLOAD METHODS --------------------------- @@ -534,71 +903,44 @@ hytiny-stm32f103t.menu.upload_method.jlinkMethod.upload.protocol=jlink hytiny-stm32f103t.menu.upload_method.jlinkMethod.upload.tool=jlink_upload hytiny-stm32f103t.menu.upload_method.jlinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER +#-- CPU Clock frequency +hytiny-stm32f103t.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +hytiny-stm32f103t.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L -###################### Generic GD32F103C ######################################## +hytiny-stm32f103t.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +hytiny-stm32f103t.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L -genericGD32F103C.name=Generic GD32F103C series -genericGD32F103C.build.variant=generic_GD32f103c -genericGD32F103C.build.vect=VECT_TAB_ADDR=0x8000000 -genericGD32F103C.build.core=maple -genericGD32F103C.build.board=GENERIC_GD32F103C -genericGD32F103C.upload.use_1200bps_touch=false -genericGD32F103C.upload.file_type=bin -genericGD32F103C.upload.auto_reset=true -genericGD32F103C.build.cpu_flags=-DMCU_STM32F103CB -genericGD32F103C.build.f_cpu=72000000L +hytiny-stm32f103t.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +hytiny-stm32f103t.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L -## GD32F103CB ------------------------- -genericGD32F103C.menu.device_variant.GD32F103CB=GD32F103CB (20k RAM. 128k Flash) -genericGD32F103C.menu.device_variant.GD32F103CB.build.ldscript=ld/jtag.ld -genericGD32F103C.menu.device_variant.GD32F103CB.upload.maximum_size=131072 -genericGD32F103C.menu.device_variant.GD32F103CB.upload.ram.maximum_size=20480 -genericGD32F103C.menu.device_variant.GD32F103CB.upload.flash.maximum_size=131072 - - -## GD32F103C8 ------------------------- -genericGD32F103C.menu.device_variant.GD32F103C8=GD32F103C8 (20k RAM. 64k Flash) -genericGD32F103C.menu.device_variant.GD32F103C8.build.ldscript=ld/jtag_c8.ld -genericGD32F103C.menu.device_variant.GD32F103C8.upload.maximum_size=65536 -genericGD32F103C.menu.device_variant.GD32F103C8.upload.ram.maximum_size=20480 -genericGD32F103C.menu.device_variant.GD32F103C8.upload.flash.maximum_size=65536 - -#---------------------------- UPLOAD METHODS --------------------------- - -genericGD32F103C.menu.upload_method.DFUUploadMethod=GD32duino bootloader - -genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu -genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload -genericGD32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -genericGD32F103C.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 -genericGD32F103C.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld -genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 -genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.altID=2 - -genericGD32F103C.menu.upload_method.serialMethod=Serial -genericGD32F103C.menu.upload_method.serialMethod.upload.protocol=maple_serial -genericGD32F103C.menu.upload_method.serialMethod.upload.tool=serial_upload -genericGD32F103C.menu.upload_method.serialMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 - -genericGD32F103C.menu.upload_method.STLinkMethod=STLink -genericGD32F103C.menu.upload_method.STLinkMethod.upload.protocol=STLink -genericGD32F103C.menu.upload_method.STLinkMethod.upload.tool=stlink_upload -genericGD32F103C.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER - - -genericGD32F103C.menu.upload_method.BMPMethod=BMP (Black Magic Probe) -genericGD32F103C.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp -genericGD32F103C.menu.upload_method.BMPMethod.upload.tool=bmp_upload -genericGD32F103C.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG - -genericGD32F103C.menu.cpu_speed.speed_120mhz=120Mhz (overdrive) -genericGD32F103C.menu.cpu_speed.speed_120mhz.build.f_cpu=120000000L - -genericGD32F103C.menu.cpu_speed.speed_96mhz=96Mhz (Stable) -genericGD32F103C.menu.cpu_speed.speed_96mhz.build.f_cpu=96000000L - -genericGD32F103C.menu.cpu_speed.speed_72mhz=72Mhz (compatibility) -genericGD32F103C.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L +#-- Optimizations +hytiny-stm32f103t.menu.opt.osstd=Smallest (default) +hytiny-stm32f103t.menu.opt.osstd.build.flags.optimize=-Os +hytiny-stm32f103t.menu.opt.osstd.build.flags.ldspecs= +hytiny-stm32f103t.menu.opt.oslto=Smallest Code with LTO +hytiny-stm32f103t.menu.opt.oslto.build.flags.optimize=-Os -flto +hytiny-stm32f103t.menu.opt.oslto.build.flags.ldspecs=-flto +hytiny-stm32f103t.menu.opt.o1std=Fast (-O1) +hytiny-stm32f103t.menu.opt.o1std.build.flags.optimize=-O1 +hytiny-stm32f103t.menu.opt.o1std.build.flags.ldspecs= +hytiny-stm32f103t.menu.opt.o1lto=Fast (-O1) with LTO +hytiny-stm32f103t.menu.opt.o1lto.build.flags.optimize=-O1 -flto +hytiny-stm32f103t.menu.opt.o1lto.build.flags.ldspecs=-flto +hytiny-stm32f103t.menu.opt.o2std=Faster (-O2) +hytiny-stm32f103t.menu.opt.o2std.build.flags.optimize=-O2 +hytiny-stm32f103t.menu.opt.o2std.build.flags.ldspecs= +hytiny-stm32f103t.menu.opt.o2lto=Faster (-O2) with LTO +hytiny-stm32f103t.menu.opt.o2lto.build.flags.optimize=-O2 -flto +hytiny-stm32f103t.menu.opt.o2lto.build.flags.ldspecs=-flto +hytiny-stm32f103t.menu.opt.o3std=Fastest (-O3) +hytiny-stm32f103t.menu.opt.o3std.build.flags.optimize=-O3 +hytiny-stm32f103t.menu.opt.o3std.build.flags.ldspecs= +hytiny-stm32f103t.menu.opt.o3lto=Fastest (-O3) with LTO +hytiny-stm32f103t.menu.opt.o3lto.build.flags.optimize=-O3 -flto +hytiny-stm32f103t.menu.opt.ogstd=Debug (-g) +hytiny-stm32f103t.menu.opt.o3lto.build.flags.ldspecs=-flto +hytiny-stm32f103t.menu.opt.ogstd.build.flags.optimize=-Og +hytiny-stm32f103t.menu.opt.ogstd.build.flags.ldspecs= ########################### STM32VLD to FLASH ########################### @@ -620,13 +962,51 @@ STM32VLD.upload.auto_reset=true STM32VLD.upload.params.quiet=no STM32VLD.build.cpu_flags=-DMCU_STM32F100RB -##---------------------------- UPLOAD METHODS --------------------------- +#---------------------------- UPLOAD METHODS --------------------------- STM32VLD.menu.upload_method.STLinkMethod=STLink STM32VLD.menu.upload_method.STLinkMethod.upload.protocol=STLink STM32VLD.menu.upload_method.STLinkMethod.upload.tool=stlink_upload STM32VLD.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG +#-- CPU Clock frequency +STM32VLD.menu.cpu_speed.speed_72mhz=72Mhz (Normal) +STM32VLD.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L + +STM32VLD.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) +STM32VLD.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L + +STM32VLD.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD +STM32VLD.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L + +#-- Optimizations +STM32VLD.menu.opt.osstd=Smallest (default) +STM32VLD.menu.opt.osstd.build.flags.optimize=-Os +STM32VLD.menu.opt.osstd.build.flags.ldspecs= +STM32VLD.menu.opt.oslto=Smallest Code with LTO +STM32VLD.menu.opt.oslto.build.flags.optimize=-Os -flto +STM32VLD.menu.opt.oslto.build.flags.ldspecs=-flto +STM32VLD.menu.opt.o1std=Fast (-O1) +STM32VLD.menu.opt.o1std.build.flags.optimize=-O1 +STM32VLD.menu.opt.o1std.build.flags.ldspecs= +STM32VLD.menu.opt.o1lto=Fast (-O1) with LTO +STM32VLD.menu.opt.o1lto.build.flags.optimize=-O1 -flto +STM32VLD.menu.opt.o1lto.build.flags.ldspecs=-flto +STM32VLD.menu.opt.o2std=Faster (-O2) +STM32VLD.menu.opt.o2std.build.flags.optimize=-O2 +STM32VLD.menu.opt.o2std.build.flags.ldspecs= +STM32VLD.menu.opt.o2lto=Faster (-O2) with LTO +STM32VLD.menu.opt.o2lto.build.flags.optimize=-O2 -flto +STM32VLD.menu.opt.o2lto.build.flags.ldspecs=-flto +STM32VLD.menu.opt.o3std=Fastest (-O3) +STM32VLD.menu.opt.o3std.build.flags.optimize=-O3 +STM32VLD.menu.opt.o3std.build.flags.ldspecs= +STM32VLD.menu.opt.o3lto=Fastest (-O3) with LTO +STM32VLD.menu.opt.o3lto.build.flags.optimize=-O3 -flto +STM32VLD.menu.opt.ogstd=Debug (-g) +STM32VLD.menu.opt.o3lto.build.flags.ldspecs=-flto +STM32VLD.menu.opt.ogstd.build.flags.optimize=-Og +STM32VLD.menu.opt.ogstd.build.flags.ldspecs= ################################################################################ diff --git a/STM32F1/cores/maple/HardwareSerial.cpp b/STM32F1/cores/maple/HardwareSerial.cpp index c993bdf..b25dafc 100644 --- a/STM32F1/cores/maple/HardwareSerial.cpp +++ b/STM32F1/cores/maple/HardwareSerial.cpp @@ -37,59 +37,6 @@ #include #include -#if 0 - - #define DEFINE_HWSERIAL(name, n) \ - HardwareSerial name(USART##n, \ - BOARD_USART##n##_TX_PIN, \ - BOARD_USART##n##_RX_PIN) - - #define DEFINE_HWSERIAL_UART(name, n) \ - HardwareSerial name(UART##n, \ - BOARD_USART##n##_TX_PIN, \ - BOARD_USART##n##_RX_PIN) - - #ifdef SERIAL_USB - #if BOARD_HAVE_USART1 - DEFINE_HWSERIAL(Serial1, 1); - #endif - #if BOARD_HAVE_USART2 - DEFINE_HWSERIAL(Serial2, 2); - #endif - #if BOARD_HAVE_USART3 - DEFINE_HWSERIAL(Serial3, 3); - #endif - #if BOARD_HAVE_UART4 - DEFINE_HWSERIAL_UART(Serial4, 4); - #endif - #if BOARD_HAVE_UART5 - DEFINE_HWSERIAL_UART(Serial5, 5); - #endif - #if BOARD_HAVE_USART6 - DEFINE_HWSERIAL_UART(Serial6, 6); - #endif - #else - #if BOARD_HAVE_USART1 - DEFINE_HWSERIAL(Serial, 1); - #endif - #if BOARD_HAVE_USART2 - DEFINE_HWSERIAL(Serial1, 2); - #endif - #if BOARD_HAVE_USART3 - DEFINE_HWSERIAL(Serial2, 3); - #endif - #if BOARD_HAVE_UART4 - DEFINE_HWSERIAL_UART(Serial3, 4); - #endif - #if BOARD_HAVE_UART5 - DEFINE_HWSERIAL_UART(Serial4, 5); - #endif - #if BOARD_HAVE_USART6 - DEFINE_HWSERIAL_UART(Serial5, 6); - #endif - #endif - -#endif HardwareSerial::HardwareSerial(usart_dev *usart_device, uint8 tx_pin, uint8 rx_pin) { @@ -193,7 +140,8 @@ size_t HardwareSerial::write(unsigned char ch) { return 1; } +/* edogaldo: Waits for the transmission of outgoing serial data to complete (Arduino 1.0 api specs) */ void HardwareSerial::flush(void) { - usart_reset_rx(this->usart_device); - usart_reset_tx(this->usart_device); + while(!rb_is_empty(this->usart_device->wb)); // wait for TX buffer empty + while(!((this->usart_device->regs->SR) & (1< // for CYCLES_PER_MICROSECOND +#include // TODO [0.1.0] Remove deprecated pieces @@ -138,32 +139,24 @@ void HardwareTimer::detachInterrupt(int channel) { timer_detach_interrupt(this->dev, (uint8)channel); } +void HardwareTimer::enableDMA(int channel) { + timer_dma_enable_req(this->dev, (uint8)channel); +} + +void HardwareTimer::disableDMA(int channel) { + timer_dma_disable_req(this->dev, (uint8)channel); +} + void HardwareTimer::refresh(void) { timer_generate_update(this->dev); } -/* CARLOS Changes to add encoder mode.*/ +void HardwareTimer::setMasterModeTrGo(uint32_t mode) { + this->dev->regs.bas->CR2 &= ~TIMER_CR2_MMS; + this->dev->regs.bas->CR2 |= mode; +} -//direction of movement. (to be better described). - uint8 HardwareTimer::getDirection(){ - return get_direction(this->dev); - } -//set if the encoder will count edges on one, which or both channels. - void HardwareTimer::setEdgeCounting(uint32 counting) { - (dev->regs).gen->SMCR = counting;//TIMER_SMCR_SMS_ENCODER3; //choose encoder 3, counting on - - } - - uint8 HardwareTimer::getEdgeCounting() { - return (dev->regs).gen->SMCR; - } - - - -//set the polarity of counting... not sure how interesting this is.. - void HardwareTimer::setPolarity(){} - /* -- Deprecated predefined instances -------------------------------------- */ HardwareTimer Timer1(1); diff --git a/STM32F1/cores/maple/HardwareTimer.h b/STM32F1/cores/maple/HardwareTimer.h index 45272ec..f715bbc 100644 --- a/STM32F1/cores/maple/HardwareTimer.h +++ b/STM32F1/cores/maple/HardwareTimer.h @@ -177,7 +177,8 @@ public: * This interrupt handler will be called when the timer's counter * reaches the given channel compare value. * - * @param channel the channel to attach the ISR to, from 1 to 4. + * @param channel the channel to attach the ISR to, from 0 to 4. + * Channel 0 is for overflow interrupt (update interrupt). * @param handler The ISR to attach to the given channel. * @see voidFuncPtr */ @@ -189,7 +190,8 @@ public: * * The handler will no longer be called by this timer. * - * @param channel the channel whose interrupt to detach, from 1 to 4. + * @param channel the channel whose interrupt to detach, from 0 to 4. + * Channel 0 is for overflow interrupt (update interrupt). * @see HardwareTimer::attachInterrupt() */ void detachInterrupt(int channel); @@ -209,24 +211,68 @@ public: */ void refresh(void); + // SYFRE + /** + * @brief Set the Master mode TRGO signal + * These bits allow to select the information to be sent in master mode to slave timers for + * synchronization (TRGO). + * mode: + * TIMER_CR2_MMS_RESET + * TIMER_CR2_MMS_ENABLE + * TIMER_CR2_MMS_UPDATE + * TIMER_CR2_MMS_COMPARE_PULSE + * TIMER_CR2_MMS_COMPARE_OC1REF + * TIMER_CR2_MMS_COMPARE_OC2REF + * TIMER_CR2_MMS_COMPARE_OC3REF + * TIMER_CR2_MMS_COMPARE_OC4REF + */ + void setMasterModeTrGo(uint32_t mode); + + void setSlaveFlags(uint32 flags) { + ((this->dev)->regs).gen->SMCR = flags; + } + //CARLOS. /* added these functions to make sense for the encoder mode. */ //direction of movement. (to be better described). - uint8 getDirection(); - + uint8 getDirection() { + return get_direction(this->dev); + } + //set if the encoder will count edges on one, which or both channels. - void setEdgeCounting(uint32 counting); - uint8 getEdgeCounting(); //not sure if needed. + void setEdgeCounting(uint32 counting) { + setSlaveFlags(counting); + } //set the polarity of counting... not sure how interesting this is.. - void setPolarity(); - + void setPolarity(uint8 channel, uint8 pol) { + timer_cc_set_pol(this->dev, channel, pol); + } + + void setInputCaptureMode(uint8 channel, timer_ic_input_select input) { + input_capture_mode(this->dev, channel, input); + } + + uint8_t getInputCaptureFlag(uint8 channel) { + return ( timer_get_status(this->dev) >> channel ) & 0x1; + } + + uint8_t getInputCaptureFlagOverflow(uint8 channel) { + uint8 ret = ( timer_get_status(this->dev) >> (8+channel) ) & 0x1; + if ( ret ) timer_reset_status_bit(this->dev, (8+channel)); // clear flag + return ret; + } + //add the filtering definition for the input channel. - /* Escape hatch */ + /** + * @brief Enable/disable DMA request for the input channel. + */ + void enableDMA(int channel); + void disableDMA(int channel); /** * @brief Get a pointer to the underlying libmaple timer_dev for diff --git a/STM32F1/cores/maple/Print.cpp b/STM32F1/cores/maple/Print.cpp index 76f386b..a8aa07d 100644 --- a/STM32F1/cores/maple/Print.cpp +++ b/STM32F1/cores/maple/Print.cpp @@ -47,12 +47,8 @@ */ size_t Print::write(const char *str) { - size_t n = 0; - while (*str) { - write(*str++); - n++; - } - return n; + if (str == NULL) return 0; + return write((const uint8_t *)str, strlen(str)); } size_t Print::write(const void *buffer, uint32 size) { @@ -99,10 +95,6 @@ size_t Print::print(unsigned long n, int base) { } size_t Print::print(long long n, int base) { - if (base == BYTE) - { - return write((uint8)n); - } if (n < 0) { print('-'); n = -n; @@ -111,13 +103,7 @@ size_t Print::print(long long n, int base) { } size_t Print::print(unsigned long long n, int base) { -size_t c=0; - if (base == BYTE) { - c= write((uint8)n); - } else { - c= printNumber(n, base); - } - return c; + return printNumber(n, base); } size_t Print::print(double n, int digits) { diff --git a/STM32F1/cores/maple/Print.h b/STM32F1/cores/maple/Print.h index bd37385..f265fac 100644 --- a/STM32F1/cores/maple/Print.h +++ b/STM32F1/cores/maple/Print.h @@ -28,7 +28,6 @@ #include "Printable.h" enum { - BYTE = 0, BIN = 2, OCT = 8, DEC = 10, diff --git a/STM32F1/cores/maple/itoa.c b/STM32F1/cores/maple/itoa.c index fc35766..33efd14 100644 --- a/STM32F1/cores/maple/itoa.c +++ b/STM32F1/cores/maple/itoa.c @@ -120,8 +120,12 @@ extern char* ltoa( long value, char *string, int radix ) return string; } - -extern char* utoa( unsigned long value, char *string, int radix ) +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \ + (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2))) +extern char* utoa( unsigned value, char *string, int radix ) +#else +extern char* utoa( unsigned int value, char *string, int radix ) +#endif { return ultoa( value, string, radix ) ; } diff --git a/STM32F1/cores/maple/itoa.h b/STM32F1/cores/maple/itoa.h index 59af109..9997b65 100644 --- a/STM32F1/cores/maple/itoa.h +++ b/STM32F1/cores/maple/itoa.h @@ -31,7 +31,12 @@ extern void itoa( int n, char s[] ) ; extern char* itoa( int value, char *string, int radix ) ; extern char* ltoa( long value, char *string, int radix ) ; -extern char* utoa( unsigned long value, char *string, int radix ) ; +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \ + (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2))) +extern char* utoa( unsigned value, char *string, int radix ) ; +#else +extern char* utoa( unsigned int value, char *string, int radix ) ; +#endif extern char* ultoa( unsigned long value, char *string, int radix ) ; #endif /* 0 */ diff --git a/STM32F1/cores/maple/libmaple/adc.c b/STM32F1/cores/maple/libmaple/adc.c index 7c48ee4..416cfaa 100644 --- a/STM32F1/cores/maple/libmaple/adc.c +++ b/STM32F1/cores/maple/libmaple/adc.c @@ -59,6 +59,7 @@ void adc_set_extsel(adc_dev *dev, adc_extsel_event event) { uint32 cr2 = dev->regs->CR2; cr2 &= ~ADC_CR2_EXTSEL; cr2 |= event; + cr2 |= ADC_CR2_EXTTRIG; dev->regs->CR2 = cr2; } diff --git a/STM32F1/cores/maple/libmaple/adc_f1.c b/STM32F1/cores/maple/libmaple/adc_f1.c index d099f6d..a8ea30b 100644 --- a/STM32F1/cores/maple/libmaple/adc_f1.c +++ b/STM32F1/cores/maple/libmaple/adc_f1.c @@ -72,7 +72,7 @@ adc_dev *ADC3 = &adc3; adc irq routine. Added by bubulindo. */ -void __irq_adc() { +__weak void __irq_adc() { //get status uint32 adc_sr = ADC1->regs->SR; //End Of Conversion @@ -107,7 +107,7 @@ void __irq_adc() { added by bubulindo */ #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -void __irq_adc3() { +__weak void __irq_adc3() { //get status uint32 adc_sr = ADC3->regs->SR; //End Of Conversion @@ -175,8 +175,8 @@ void adc_attach_interrupt(adc_dev *dev, * @param dev adc device */ void adc_calibrate(adc_dev *dev) { - __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); - __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); + __IO uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); + __IO uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); *rstcal_bit = 1; while (*rstcal_bit) @@ -203,7 +203,7 @@ void adc_foreach(void (*fn)(adc_dev*)) { #endif } -void adc_config_gpio(adc_dev *ignored, gpio_dev *gdev, uint8 bit) { +void adc_config_gpio(adc_dev *ignored __attribute__((unused)), gpio_dev *gdev, uint8 bit) { gpio_set_mode(gdev, bit, GPIO_INPUT_ANALOG); } diff --git a/STM32F1/cores/maple/libmaple/bkp_f1.c b/STM32F1/cores/maple/libmaple/bkp_f1.c index 01ad419..741f5eb 100644 --- a/STM32F1/cores/maple/libmaple/bkp_f1.c +++ b/STM32F1/cores/maple/libmaple/bkp_f1.c @@ -34,7 +34,7 @@ #include #include -static inline __io uint32* data_register(uint8 reg); +static inline __IO uint32* data_register(uint8 reg); bkp_dev bkp = { .regs = BKP_BASE, @@ -78,7 +78,7 @@ void bkp_disable_writes(void) { * medium-density devices, 42 on high-density devices). */ uint16 bkp_read(uint8 reg) { - __io uint32* dr = data_register(reg); + __IO uint32* dr = data_register(reg); if (!dr) { ASSERT(0); /* nonexistent register */ return 0; @@ -97,7 +97,7 @@ uint16 bkp_read(uint8 reg) { * @see bkp_enable_writes() */ void bkp_write(uint8 reg, uint16 val) { - __io uint32* dr = data_register(reg); + __IO uint32* dr = data_register(reg); if (!dr) { ASSERT(0); /* nonexistent register */ return; @@ -112,7 +112,7 @@ void bkp_write(uint8 reg, uint16 val) { */ #define NR_LOW_DRS 10 -static inline __io uint32* data_register(uint8 reg) { +static inline __IO uint32* data_register(uint8 reg) { if (reg < 1 || reg > BKP_NR_DATA_REGS) { return 0; } diff --git a/STM32F1/cores/maple/libmaple/dma.c b/STM32F1/cores/maple/libmaple/dma.c index d13de10..1dc875e 100644 --- a/STM32F1/cores/maple/libmaple/dma.c +++ b/STM32F1/cores/maple/libmaple/dma.c @@ -52,7 +52,7 @@ void dma_init(dma_dev *dev) { * Private API */ -enum dma_atype _dma_addr_type(__io void *addr) { +enum dma_atype _dma_addr_type(__IO void *addr) { switch (stm32_block_purpose((void*)addr)) { /* Notice we're treating the code block as memory here. That's * correct for addresses in Flash and in [0x0, 0x7FFFFFF] diff --git a/STM32F1/cores/maple/libmaple/dma_f1.c b/STM32F1/cores/maple/libmaple/dma_f1.c index 6400d15..fb5b03c 100644 --- a/STM32F1/cores/maple/libmaple/dma_f1.c +++ b/STM32F1/cores/maple/libmaple/dma_f1.c @@ -86,7 +86,7 @@ static int cfg_dev_ok(dma_dev *dev, dma_tube_config *cfg) { } /* Is addr acceptable for use as DMA src/dst? */ -static int cfg_mem_ok(__io void *addr) { +static int cfg_mem_ok(__IO void *addr) { enum dma_atype atype = _dma_addr_type(addr); return atype == DMA_ATYPE_MEM || atype == DMA_ATYPE_PER; } @@ -293,7 +293,7 @@ dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) { return DMA_TRANSFER_ERROR; } -void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { +void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __IO void *addr) { dma_channel_reg_map *chan_regs; ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); @@ -302,7 +302,7 @@ void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { chan_regs->CMAR = (uint32)addr; } -void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { +void dma_set_per_addr(dma_dev *dev, dma_channel channel, __IO void *addr) { dma_channel_reg_map *chan_regs; ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); @@ -341,12 +341,11 @@ void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { * @see dma_attach_interrupt() * @see dma_enable() */ -__deprecated void dma_setup_transfer(dma_dev *dev, dma_channel channel, - __io void *peripheral_address, + __IO void *peripheral_address, dma_xfer_size peripheral_size, - __io void *memory_address, + __IO void *memory_address, dma_xfer_size memory_size, uint32 mode) { dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel); @@ -361,48 +360,48 @@ void dma_setup_transfer(dma_dev *dev, * IRQ handlers */ -void __irq_dma1_channel1(void) { +__weak void __irq_dma1_channel1(void) { dma_irq_handler(DMA1, DMA_CH1); } -void __irq_dma1_channel2(void) { +__weak void __irq_dma1_channel2(void) { dma_irq_handler(DMA1, DMA_CH2); } -void __irq_dma1_channel3(void) { +__weak void __irq_dma1_channel3(void) { dma_irq_handler(DMA1, DMA_CH3); } -void __irq_dma1_channel4(void) { +__weak void __irq_dma1_channel4(void) { dma_irq_handler(DMA1, DMA_CH4); } -void __irq_dma1_channel5(void) { +__weak void __irq_dma1_channel5(void) { dma_irq_handler(DMA1, DMA_CH5); } -void __irq_dma1_channel6(void) { +__weak void __irq_dma1_channel6(void) { dma_irq_handler(DMA1, DMA_CH6); } -void __irq_dma1_channel7(void) { +__weak void __irq_dma1_channel7(void) { dma_irq_handler(DMA1, DMA_CH7); } #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -void __irq_dma2_channel1(void) { +__weak void __irq_dma2_channel1(void) { dma_irq_handler(DMA2, DMA_CH1); } -void __irq_dma2_channel2(void) { +__weak void __irq_dma2_channel2(void) { dma_irq_handler(DMA2, DMA_CH2); } -void __irq_dma2_channel3(void) { +__weak void __irq_dma2_channel3(void) { dma_irq_handler(DMA2, DMA_CH3); } -void __irq_dma2_channel4_5(void) { +__weak void __irq_dma2_channel4_5(void) { if ((DMA2_BASE->CCR4 & DMA_CCR_EN) && (DMA2_BASE->ISR & DMA_ISR_GIF4)) { dma_irq_handler(DMA2, DMA_CH4); } diff --git a/STM32F1/cores/maple/libmaple/exc.S b/STM32F1/cores/maple/libmaple/exc.S index 7631e48..24153fc 100644 --- a/STM32F1/cores/maple/libmaple/exc.S +++ b/STM32F1/cores/maple/libmaple/exc.S @@ -41,7 +41,6 @@ # SP--> r0 .text -.globl __exc_hardfault .globl __exc_nmi .globl __exc_hardfault .globl __exc_memmanage diff --git a/STM32F1/cores/maple/libmaple/exti.c b/STM32F1/cores/maple/libmaple/exti.c index 402bec6..982ba06 100644 --- a/STM32F1/cores/maple/libmaple/exti.c +++ b/STM32F1/cores/maple/libmaple/exti.c @@ -200,7 +200,7 @@ void exti_detach_interrupt(exti_num num) { * Private routines */ -void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port) { +void exti_do_select(__IO uint32 *exti_cr, exti_num num, exti_cfg port) { uint32 shift = 4 * (num % 4); uint32 cr = *exti_cr; cr &= ~(0xF << shift); @@ -212,31 +212,31 @@ void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port) { * Interrupt handlers */ -void __irq_exti0(void) { +__weak void __irq_exti0(void) { dispatch_single_exti(EXTI0); } -void __irq_exti1(void) { +__weak void __irq_exti1(void) { dispatch_single_exti(EXTI1); } -void __irq_exti2(void) { +__weak void __irq_exti2(void) { dispatch_single_exti(EXTI2); } -void __irq_exti3(void) { +__weak void __irq_exti3(void) { dispatch_single_exti(EXTI3); } -void __irq_exti4(void) { +__weak void __irq_exti4(void) { dispatch_single_exti(EXTI4); } -void __irq_exti9_5(void) { +__weak void __irq_exti9_5(void) { dispatch_extis(5, 9); } -void __irq_exti15_10(void) { +__weak void __irq_exti15_10(void) { dispatch_extis(10, 15); } diff --git a/STM32F1/cores/maple/libmaple/gpio_f1.c b/STM32F1/cores/maple/libmaple/gpio_f1.c index ecd015d..0db1f1a 100644 --- a/STM32F1/cores/maple/libmaple/gpio_f1.c +++ b/STM32F1/cores/maple/libmaple/gpio_f1.c @@ -68,7 +68,7 @@ gpio_dev gpiod = { /** GPIO port D device. */ gpio_dev* const GPIOD = &gpiod; -#ifdef STM32_HIGH_DENSITY +#if STM32_NR_GPIO_PORTS > 4 gpio_dev gpioe = { .regs = GPIOE_BASE, .clk_id = RCC_GPIOE, @@ -106,7 +106,7 @@ void gpio_init_all(void) { gpio_init(GPIOB); gpio_init(GPIOC); gpio_init(GPIOD); -#ifdef STM32_HIGH_DENSITY +#if STM32_NR_GPIO_PORTS > 4 gpio_init(GPIOE); gpio_init(GPIOF); gpio_init(GPIOG); @@ -123,7 +123,7 @@ void gpio_init_all(void) { */ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { gpio_reg_map *regs = dev->regs; - __io uint32 *cr = ®s->CRL + (pin >> 3); + __IO uint32 *cr = ®s->CRL + (pin >> 3); uint32 shift = (pin & 0x7) * 4; uint32 tmp = *cr; @@ -140,9 +140,8 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { gpio_pin_mode gpio_get_mode(gpio_dev *dev, uint8 pin) { gpio_reg_map *regs = dev->regs; - __io uint32 *cr = ®s->CRL + (pin >> 3); + __IO uint32 *cr = ®s->CRL + (pin >> 3); uint32 shift = (pin & 0x7) * 4; - uint32 tmp = *cr; uint32 crMode = (*cr>>shift) & 0x0F; diff --git a/STM32F1/cores/maple/libmaple/i2c.c b/STM32F1/cores/maple/libmaple/i2c.c index c4ed245..6724d16 100644 --- a/STM32F1/cores/maple/libmaple/i2c.c +++ b/STM32F1/cores/maple/libmaple/i2c.c @@ -324,7 +324,7 @@ void _i2c_irq_handler(i2c_dev *dev) { /* * EV6: Slave address sent */ - if (sr1 & I2C_SR1_ADDR) { + if (sr1 & (I2C_SR1_ADDR|I2C_SR1_ADD10)) { /* * Special case event EV6_1 for master receiver. * Generate NACK and restart/stop condition after ADDR diff --git a/STM32F1/cores/maple/libmaple/i2c_f1.c b/STM32F1/cores/maple/libmaple/i2c_f1.c index 8439793..3b1cc36 100644 --- a/STM32F1/cores/maple/libmaple/i2c_f1.c +++ b/STM32F1/cores/maple/libmaple/i2c_f1.c @@ -76,19 +76,19 @@ void i2c_master_release_bus(const i2c_dev *dev) { * IRQ handlers */ -void __irq_i2c1_ev(void) { +__weak void __irq_i2c1_ev(void) { _i2c_irq_handler(I2C1); } -void __irq_i2c2_ev(void) { +__weak void __irq_i2c2_ev(void) { _i2c_irq_handler(I2C2); } -void __irq_i2c1_er(void) { +__weak void __irq_i2c1_er(void) { _i2c_irq_error_handler(I2C1); } -void __irq_i2c2_er(void) { +__weak void __irq_i2c2_er(void) { _i2c_irq_error_handler(I2C2); } diff --git a/STM32F1/cores/maple/libmaple/rcc.c b/STM32F1/cores/maple/libmaple/rcc.c index 8e7d1ea..aba87c0 100644 --- a/STM32F1/cores/maple/libmaple/rcc.c +++ b/STM32F1/cores/maple/libmaple/rcc.c @@ -94,8 +94,8 @@ void rcc_switch_sysclk(rcc_sysclk_src sysclk_src) { * won't work for you. */ /* Returns the RCC register which controls the clock source. */ -static inline __io uint32* rcc_clk_reg(rcc_clk clock) { - return (__io uint32*)((__io uint8*)RCC_BASE + (clock >> 8)); +static inline __IO uint32* rcc_clk_reg(rcc_clk clock) { + return (__IO uint32*)((__IO uint8*)RCC_BASE + (clock >> 8)); } /* Returns a mask in rcc_clk_reg(clock) to be used for turning the diff --git a/STM32F1/cores/maple/libmaple/rcc_f1.c b/STM32F1/cores/maple/libmaple/rcc_f1.c index f45f670..3fc916a 100644 --- a/STM32F1/cores/maple/libmaple/rcc_f1.c +++ b/STM32F1/cores/maple/libmaple/rcc_f1.c @@ -69,10 +69,12 @@ const struct rcc_dev_info rcc_dev_table[] = { [RCC_FLITF] = { .clk_domain = AHB, .line_num = 4}, [RCC_SRAM] = { .clk_domain = AHB, .line_num = 2}, [RCC_USB] = { .clk_domain = APB1, .line_num = 23}, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +#if STM32_NR_GPIO_PORTS > 4 [RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 }, [RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 }, [RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 }, +#endif +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) [RCC_UART4] = { .clk_domain = APB1, .line_num = 19 }, [RCC_UART5] = { .clk_domain = APB1, .line_num = 20 }, [RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, @@ -132,11 +134,17 @@ void rcc_configure_pll(rcc_pll_cfg *pll_cfg) { cfgr &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL); cfgr |= pll_cfg->pllsrc | pll_mul; +#ifdef XTAL16M + // 16MHz crystal (HSE) + // in this case we additionally set the Bit 17 (PLLXTPRE=1) => then HSE clock is divided by 2 before PLL entry + cfgr |= RCC_CFGR_PLLXTPRE; +#endif + RCC_BASE->CFGR = cfgr; } void rcc_clk_enable(rcc_clk_id id) { - static __io uint32* enable_regs[] = { + static __IO uint32* enable_regs[] = { [APB1] = &RCC_BASE->APB1ENR, [APB2] = &RCC_BASE->APB2ENR, [AHB] = &RCC_BASE->AHBENR, @@ -145,7 +153,7 @@ void rcc_clk_enable(rcc_clk_id id) { } void rcc_reset_dev(rcc_clk_id id) { - static __io uint32* reset_regs[] = { + static __IO uint32* reset_regs[] = { [APB1] = &RCC_BASE->APB1RSTR, [APB2] = &RCC_BASE->APB2RSTR, }; @@ -164,7 +172,7 @@ void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { } void rcc_clk_disable(rcc_clk_id id) { - static __io uint32* enable_regs[] = { + static __IO uint32* enable_regs[] = { [APB1] = &RCC_BASE->APB1ENR, [APB2] = &RCC_BASE->APB2ENR, [AHB] = &RCC_BASE->AHBENR, diff --git a/STM32F1/cores/maple/libmaple/spi.c b/STM32F1/cores/maple/libmaple/spi.c index 1020c5b..e0ee90d 100644 --- a/STM32F1/cores/maple/libmaple/spi.c +++ b/STM32F1/cores/maple/libmaple/spi.c @@ -84,7 +84,7 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) { } /** - * @brief Nonblocking SPI transmit. + * @brief Blocking SPI transmit. * @param dev SPI port to use for transmission * @param buf Buffer to transmit. The sizeof buf's elements are * inferred from dev's data frame format (i.e., are @@ -93,15 +93,21 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) { * @return Number of elements transmitted. */ uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) { - uint32 txed = 0; - uint8 byte_frame = spi_dff(dev) == SPI_DFF_8_BIT; - while (spi_is_tx_empty(dev) && (txed < len)) { - if (byte_frame) { - dev->regs->DR = ((const uint8*)buf)[txed++]; - } else { - dev->regs->DR = ((const uint16*)buf)[txed++]; - } - } + uint32 txed = len; + spi_reg_map *regs = dev->regs; + if ( spi_dff(dev) == SPI_DFF_8_BIT ) { + const uint8 * dp8 = (const uint8*)buf; + while ( len-- ) { + while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty + regs->DR = *dp8++; + } + } else { + const uint16 * dp16 = (const uint16*)buf; + while ( len-- ) { + while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty + regs->DR = *dp16++; + } + } return txed; } diff --git a/STM32F1/cores/maple/libmaple/spi_f1.c b/STM32F1/cores/maple/libmaple/spi_f1.c index bbea5a4..d920761 100644 --- a/STM32F1/cores/maple/libmaple/spi_f1.c +++ b/STM32F1/cores/maple/libmaple/spi_f1.c @@ -54,7 +54,7 @@ spi_dev *SPI3 = &spi3; * Routines */ -void spi_config_gpios(spi_dev *ignored, +void spi_config_gpios(spi_dev *ignored __attribute__((unused)), uint8 as_master, gpio_dev *nss_dev, uint8 nss_bit, diff --git a/STM32F1/cores/maple/libmaple/stm32f1/performance/isrs.S b/STM32F1/cores/maple/libmaple/stm32f1/performance/isrs.S index 8c1a44f..7a9b4aa 100644 --- a/STM32F1/cores/maple/libmaple/stm32f1/performance/isrs.S +++ b/STM32F1/cores/maple/libmaple/stm32f1/performance/isrs.S @@ -76,9 +76,9 @@ __default_handler: .weak __exc_pendsv .globl __exc_pendsv .set __exc_pendsv, __default_handler - .weak __exc_systick - .globl __exc_systick - .set __exc_systick, __default_handler +// .weak __exc_systick // __exc_systick() defined in STM32F1/cores/maple/libmaple/systick.c +// .globl __exc_systick +// .set __exc_systick, __default_handler .weak __irq_wwdg .globl __irq_wwdg .set __irq_wwdg, __default_handler @@ -97,110 +97,110 @@ __default_handler: .weak __irq_rcc .globl __irq_rcc .set __irq_rcc, __default_handler - .weak __irq_exti0 - .globl __irq_exti0 - .set __irq_exti0, __default_handler - .weak __irq_exti1 - .globl __irq_exti1 - .set __irq_exti1, __default_handler - .weak __irq_exti2 - .globl __irq_exti2 - .set __irq_exti2, __default_handler - .weak __irq_exti3 - .globl __irq_exti3 - .set __irq_exti3, __default_handler - .weak __irq_exti4 - .globl __irq_exti4 - .set __irq_exti4, __default_handler - .weak __irq_dma1_channel1 - .globl __irq_dma1_channel1 - .set __irq_dma1_channel1, __default_handler - .weak __irq_dma1_channel2 - .globl __irq_dma1_channel2 - .set __irq_dma1_channel2, __default_handler - .weak __irq_dma1_channel3 - .globl __irq_dma1_channel3 - .set __irq_dma1_channel3, __default_handler - .weak __irq_dma1_channel4 - .globl __irq_dma1_channel4 - .set __irq_dma1_channel4, __default_handler - .weak __irq_dma1_channel5 - .globl __irq_dma1_channel5 - .set __irq_dma1_channel5, __default_handler - .weak __irq_dma1_channel6 - .globl __irq_dma1_channel6 - .set __irq_dma1_channel6, __default_handler - .weak __irq_dma1_channel7 - .globl __irq_dma1_channel7 - .set __irq_dma1_channel7, __default_handler - .weak __irq_adc - .globl __irq_adc - .set __irq_adc, __default_handler +// .weak __irq_exti0 // __irq_exti0() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti0 +// .set __irq_exti0, __default_handler +// .weak __irq_exti1 // __irq_exti1() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti1 +// .set __irq_exti1, __default_handler +// .weak __irq_exti2 // __irq_exti2() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti2 +// .set __irq_exti2, __default_handler +// .weak __irq_exti3 // __irq_exti3() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti3 +// .set __irq_exti3, __default_handler +// .weak __irq_exti4 // __irq_exti4() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti4 +// .set __irq_exti4, __default_handler +// .weak __irq_dma1_channel1 // __irq_dma1_channel1() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel1 +// .set __irq_dma1_channel1, __default_handler +// .weak __irq_dma1_channel2 // __irq_dma1_channel2() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel2 +// .set __irq_dma1_channel2, __default_handler +// .weak __irq_dma1_channel3 // __irq_dma1_channel3() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel3 +// .set __irq_dma1_channel3, __default_handler +// .weak __irq_dma1_channel4 // __irq_dma1_channel4() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel4 +// .set __irq_dma1_channel4, __default_handler +// .weak __irq_dma1_channel5 // __irq_dma1_channel5() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel5 +// .set __irq_dma1_channel5, __default_handler +// .weak __irq_dma1_channel6 // __irq_dma1_channel6() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel6 +// .set __irq_dma1_channel6, __default_handler +// .weak __irq_dma1_channel7 // __irq_dma1_channel7() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma1_channel7 +// .set __irq_dma1_channel7, __default_handler +// .weak __irq_adc // __irq_adc() defined in STM32F1/cores/maple/libmaple/adc_f1.c +// .globl __irq_adc +// .set __irq_adc, __default_handler .weak __irq_usb_hp_can_tx .globl __irq_usb_hp_can_tx .set __irq_usb_hp_can_tx, __default_handler - .weak __irq_usb_lp_can_rx0 - .globl __irq_usb_lp_can_rx0 - .set __irq_usb_lp_can_rx0, __default_handler +// .weak __irq_usb_lp_can_rx0 // __irq_usb_lp_can_rx0() defined in STM32F1/cores/maple/libmaple/usb/stm32f1/usb.c +// .globl __irq_usb_lp_can_rx0 +// .set __irq_usb_lp_can_rx0, __default_handler .weak __irq_can_rx1 .globl __irq_can_rx1 .set __irq_can_rx1, __default_handler .weak __irq_can_sce .globl __irq_can_sce .set __irq_can_sce, __default_handler - .weak __irq_exti9_5 - .globl __irq_exti9_5 - .set __irq_exti9_5, __default_handler - .weak __irq_tim1_brk - .globl __irq_tim1_brk - .set __irq_tim1_brk, __default_handler - .weak __irq_tim1_up - .globl __irq_tim1_up - .set __irq_tim1_up, __default_handler - .weak __irq_tim1_trg_com - .globl __irq_tim1_trg_com - .set __irq_tim1_trg_com, __default_handler - .weak __irq_tim1_cc - .globl __irq_tim1_cc - .set __irq_tim1_cc, __default_handler - - .weakref __irq_tim2, __default_handler - .globl __irq_tim2 - .weakref __irq_tim3, __default_handler - .globl __irq_tim3 - .weakref __irq_tim4, __default_handler - .globl __irq_tim4 - - .weak __irq_i2c1_ev - .globl __irq_i2c1_ev - .set __irq_i2c1_ev, __default_handler - .weak __irq_i2c1_er - .globl __irq_i2c1_er - .set __irq_i2c1_er, __default_handler - .weak __irq_i2c2_ev - .globl __irq_i2c2_ev - .set __irq_i2c2_ev, __default_handler - .weak __irq_i2c2_er - .globl __irq_i2c2_er - .set __irq_i2c2_er, __default_handler +// .weak __irq_exti9_5 // __irq_exti9_5() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti9_5 +// .set __irq_exti9_5, __default_handler +// .weak __irq_tim1_brk // __irq_tim1_brk() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim1_brk +// .set __irq_tim1_brk, __default_handler +// .weak __irq_tim1_up // __irq_tim1_up() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim1_up +// .set __irq_tim1_up, __default_handler +// .weak __irq_tim1_trg_com // __irq_tim1_trg_com() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim1_trg_com +// .set __irq_tim1_trg_com, __default_handler +// .weak __irq_tim1_cc // __irq_tim1_cc() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim1_cc +// .set __irq_tim1_cc, __default_handler +// +// .weakref __irq_tim2, __default_handler // __irq_tim2() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim2 +// .weakref __irq_tim3, __default_handler // __irq_tim3() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim3 +// .weakref __irq_tim4, __default_handler // __irq_tim4() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim4 +// +// .weak __irq_i2c1_ev // __irq_i2c1_ev() defined in STM32F1/cores/maple/libmaple/i2c_f1.c +// .globl __irq_i2c1_ev +// .set __irq_i2c1_ev, __default_handler +// .weak __irq_i2c1_er // __irq_i2c1_er() defined in STM32F1/cores/maple/libmaple/i2c_f1.c +// .globl __irq_i2c1_er +// .set __irq_i2c1_er, __default_handler +// .weak __irq_i2c2_ev // __irq_i2c2_ev() defined in STM32F1/cores/maple/libmaple/i2c_f1.c +// .globl __irq_i2c2_ev +// .set __irq_i2c2_ev, __default_handler +// .weak __irq_i2c2_er // __irq_i2c2_er() defined in STM32F1/cores/maple/libmaple/i2c_f1.c +// .globl __irq_i2c2_er +// .set __irq_i2c2_er, __default_handler .weak __irq_spi1 .globl __irq_spi1 .set __irq_spi1, __default_handler .weak __irq_spi2 .globl __irq_spi2 .set __irq_spi2, __default_handler - .weak __irq_usart1 - .globl __irq_usart1 - .set __irq_usart1, __default_handler - .weak __irq_usart2 - .globl __irq_usart2 - .set __irq_usart2, __default_handler - .weak __irq_usart3 - .globl __irq_usart3 - .set __irq_usart3, __default_handler - .weak __irq_exti15_10 - .globl __irq_exti15_10 - .set __irq_exti15_10, __default_handler +// .weak __irq_usart1 // __irq_usart1() defined in STM32F1/cores/maple/libmaple/usart_f1.c +// .globl __irq_usart1 +// .set __irq_usart1, __default_handler +// .weak __irq_usart2 // __irq_usart2() defined in STM32F1/cores/maple/libmaple/usart_f1.c +// .globl __irq_usart2 +// .set __irq_usart2, __default_handler +// .weak __irq_usart3 // __irq_usart3() defined in STM32F1/cores/maple/libmaple/usart_f1.c +// .globl __irq_usart3 +// .set __irq_usart3, __default_handler +// .weak __irq_exti15_10 // __irq_exti15_10() defined in STM32F1/cores/maple/libmaple/exti.c +// .globl __irq_exti15_10 +// .set __irq_exti15_10, __default_handler .weak __irq_rtcalarm .globl __irq_rtcalarm .set __irq_rtcalarm, __default_handler @@ -208,55 +208,55 @@ __default_handler: .globl __irq_usbwakeup .set __irq_usbwakeup, __default_handler #if defined (STM32_HIGH_DENSITY) - .weak __irq_tim8_brk - .globl __irq_tim8_brk - .set __irq_tim8_brk, __default_handler - .weak __irq_tim8_up - .globl __irq_tim8_up - .set __irq_tim8_up, __default_handler - .weak __irq_tim8_trg_com - .globl __irq_tim8_trg_com - .set __irq_tim8_trg_com, __default_handler - .weak __irq_tim8_cc - .globl __irq_tim8_cc - .set __irq_tim8_cc, __default_handler - .weak __irq_adc3 - .globl __irq_adc3 - .set __irq_adc3, __default_handler +// .weak __irq_tim8_brk // __irq_tim8_brk() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim8_brk +// .set __irq_tim8_brk, __default_handler +// .weak __irq_tim8_up // __irq_tim8_up() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim8_up +// .set __irq_tim8_up, __default_handler +// .weak __irq_tim8_trg_com // __irq_tim8_trg_com() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim8_trg_com +// .set __irq_tim8_trg_com, __default_handler +// .weak __irq_tim8_cc // __irq_tim8_cc() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim8_cc +// .set __irq_tim8_cc, __default_handler +// .weak __irq_adc3 // __irq_adc3() defined in STM32F1/cores/maple/libmaple/adc_f1.c +// .globl __irq_adc3 +// .set __irq_adc3, __default_handler .weak __irq_fsmc .globl __irq_fsmc .set __irq_fsmc, __default_handler .weak __irq_sdio .globl __irq_sdio .set __irq_sdio, __default_handler - .weak __irq_tim5 - .globl __irq_tim5 - .set __irq_tim5, __default_handler +// .weak __irq_tim5 // __irq_tim5() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim5 +// .set __irq_tim5, __default_handler .weak __irq_spi3 .globl __irq_spi3 .set __irq_spi3, __default_handler - .weak __irq_uart4 - .globl __irq_uart4 - .set __irq_uart4, __default_handler - .weak __irq_uart5 - .globl __irq_uart5 - .set __irq_uart5, __default_handler - .weak __irq_tim6 - .globl __irq_tim6 - .set __irq_tim6, __default_handler - .weak __irq_tim7 - .globl __irq_tim7 - .set __irq_tim7, __default_handler - .weak __irq_dma2_channel1 - .globl __irq_dma2_channel1 - .set __irq_dma2_channel1, __default_handler - .weak __irq_dma2_channel2 - .globl __irq_dma2_channel2 - .set __irq_dma2_channel2, __default_handler - .weak __irq_dma2_channel3 - .globl __irq_dma2_channel3 - .set __irq_dma2_channel3, __default_handler - .weak __irq_dma2_channel4_5 - .globl __irq_dma2_channel4_5 - .set __irq_dma2_channel4_5, __default_handler +// .weak __irq_uart4 // __irq_uart4() defined in STM32F1/cores/maple/libmaple/usart_f1.c +// .globl __irq_uart4 +// .set __irq_uart4, __default_handler +// .weak __irq_uart5 // __irq_uart5() defined in STM32F1/cores/maple/libmaple/usart_f1.c +// .globl __irq_uart5 +// .set __irq_uart5, __default_handler +// .weak __irq_tim6 // __irq_tim6() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim6 +// .set __irq_tim6, __default_handler +// .weak __irq_tim7 // __irq_tim7() defined in STM32F1/cores/maple/libmaple/timer.c +// .globl __irq_tim7 +// .set __irq_tim7, __default_handler +// .weak __irq_dma2_channel1 // __irq_dma2_channel1() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma2_channel1 +// .set __irq_dma2_channel1, __default_handler +// .weak __irq_dma2_channel2 // __irq_dma2_channel2() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma2_channel2 +// .set __irq_dma2_channel2, __default_handler +// .weak __irq_dma2_channel3 // __irq_dma2_channel3() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma2_channel3 +// .set __irq_dma2_channel3, __default_handler +// .weak __irq_dma2_channel4_5 // __irq_dma2_channel4_5() defined in STM32F1/cores/maple/libmaple/dma_f1.c +// .globl __irq_dma2_channel4_5 +// .set __irq_dma2_channel4_5, __default_handler #endif /* STM32_HIGH_DENSITY */ \ No newline at end of file diff --git a/STM32F1/cores/maple/libmaple/systick.c b/STM32F1/cores/maple/libmaple/systick.c index 7568abe..1ac92f1 100644 --- a/STM32F1/cores/maple/libmaple/systick.c +++ b/STM32F1/cores/maple/libmaple/systick.c @@ -80,7 +80,7 @@ void systick_attach_callback(void (*callback)(void)) { * SysTick ISR */ -void __exc_systick(void) { +__weak void __exc_systick(void) { systick_uptime_millis++; if (systick_user_callback) { systick_user_callback(); diff --git a/STM32F1/cores/maple/libmaple/timer.c b/STM32F1/cores/maple/libmaple/timer.c index daf8e43..5f12430 100644 --- a/STM32F1/cores/maple/libmaple/timer.c +++ b/STM32F1/cores/maple/libmaple/timer.c @@ -40,7 +40,6 @@ static void pwm_mode(timer_dev *dev, uint8 channel); static void output_compare_mode(timer_dev *dev, uint8 channel); static void encoder_mode(timer_dev *dev, uint8 channel) ;//CARLOS - static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid); /* @@ -236,6 +235,9 @@ void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) { case TIMER_ENCODER: encoder_mode(dev, channel); //find a way to pass all the needed stuff on the 8bit var break; + case TIMER_INPUT_CAPTURE:// code from @Cesco + input_capture_mode(dev, channel, TIMER_IC_INPUT_DEFAULT); + break; } } @@ -327,7 +329,7 @@ static void output_compare_mode(timer_dev *dev, uint8 channel) { } //added by CARLOS. -static void encoder_mode(timer_dev *dev, uint8 channel) { +static void encoder_mode(timer_dev *dev, uint8 channel __attribute__((unused))) { //prescaler. //(dev->regs).gen->PSC = 1; @@ -349,7 +351,10 @@ static void encoder_mode(timer_dev *dev, uint8 channel) { timer_resume(dev); } - +void input_capture_mode(timer_dev *dev, uint8 channel, timer_ic_input_select input) { + timer_oc_set_mode(dev, channel, 0, input); + timer_cc_enable(dev, channel); +} static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id); static void enable_bas_gen_irq(timer_dev *dev); @@ -473,78 +478,78 @@ static void enable_bas_gen_irq(timer_dev *dev) { * file. */ -void __irq_tim1_brk(void) { +__weak void __irq_tim1_brk(void) { dispatch_adv_brk(TIMER1); #if STM32_HAVE_TIMER(9) dispatch_tim_9_12(TIMER9); #endif } -void __irq_tim1_up(void) { +__weak void __irq_tim1_up(void) { dispatch_adv_up(TIMER1); #if STM32_HAVE_TIMER(10) dispatch_tim_10_11_13_14(TIMER10); #endif } -void __irq_tim1_trg_com(void) { +__weak void __irq_tim1_trg_com(void) { dispatch_adv_trg_com(TIMER1); #if STM32_HAVE_TIMER(11) dispatch_tim_10_11_13_14(TIMER11); #endif } -void __irq_tim1_cc(void) { +__weak void __irq_tim1_cc(void) { dispatch_adv_cc(TIMER1); } -void __irq_tim2(void) { +__weak void __irq_tim2(void) { dispatch_general(TIMER2); } -void __irq_tim3(void) { +__weak void __irq_tim3(void) { dispatch_general(TIMER3); } -void __irq_tim4(void) { +__weak void __irq_tim4(void) { dispatch_general(TIMER4); } #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -void __irq_tim5(void) { +__weak void __irq_tim5(void) { dispatch_general(TIMER5); } -void __irq_tim6(void) { +__weak void __irq_tim6(void) { dispatch_basic(TIMER6); } -void __irq_tim7(void) { +__weak void __irq_tim7(void) { dispatch_basic(TIMER7); } -void __irq_tim8_brk(void) { +__weak void __irq_tim8_brk(void) { dispatch_adv_brk(TIMER8); #if STM32_HAVE_TIMER(12) dispatch_tim_9_12(TIMER12); #endif } -void __irq_tim8_up(void) { +__weak void __irq_tim8_up(void) { dispatch_adv_up(TIMER8); #if STM32_HAVE_TIMER(13) dispatch_tim_10_11_13_14(TIMER13); #endif } -void __irq_tim8_trg_com(void) { +__weak void __irq_tim8_trg_com(void) { dispatch_adv_trg_com(TIMER8); #if STM32_HAVE_TIMER(14) dispatch_tim_10_11_13_14(TIMER14); #endif } -void __irq_tim8_cc(void) { +__weak void __irq_tim8_cc(void) { dispatch_adv_cc(TIMER8); } #endif /* defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) */ \ No newline at end of file diff --git a/STM32F1/cores/maple/libmaple/usart_f1.c b/STM32F1/cores/maple/libmaple/usart_f1.c index 2b590fc..30ce000 100644 --- a/STM32F1/cores/maple/libmaple/usart_f1.c +++ b/STM32F1/cores/maple/libmaple/usart_f1.c @@ -200,24 +200,24 @@ void usart_foreach(void (*fn)(usart_dev*)) { * Interrupt handlers. */ -void __irq_usart1(void) { +__weak void __irq_usart1(void) { usart_irq(&usart1_rb, &usart1_wb, USART1_BASE); } -void __irq_usart2(void) { +__weak void __irq_usart2(void) { usart_irq(&usart2_rb, &usart2_wb, USART2_BASE); } -void __irq_usart3(void) { +__weak void __irq_usart3(void) { usart_irq(&usart3_rb, &usart3_wb, USART3_BASE); } #ifdef STM32_HIGH_DENSITY -void __irq_uart4(void) { +__weak void __irq_uart4(void) { usart_irq(&uart4_rb, &uart4_wb, UART4_BASE); } -void __irq_uart5(void) { +__weak void __irq_uart5(void) { usart_irq(&uart5_rb, &uart5_wb, UART5_BASE); } #endif diff --git a/STM32F1/cores/maple/libmaple/usb/stm32f1/usb.c b/STM32F1/cores/maple/libmaple/usb/stm32f1/usb.c index f837eb6..4f6c823 100644 --- a/STM32F1/cores/maple/libmaple/usb/stm32f1/usb.c +++ b/STM32F1/cores/maple/libmaple/usb/stm32f1/usb.c @@ -120,6 +120,12 @@ static void usb_suspend(void) { USBLIB->state = USB_SUSPENDED; } +void usb_power_off(void) { + USB_BASE->CNTR = USB_CNTR_FRES; + USB_BASE->ISTR = 0; + USB_BASE->CNTR = USB_CNTR_FRES + USB_CNTR_PDWN; +} + static void usb_resume_init(void) { uint16 cntr; @@ -184,7 +190,7 @@ static void usb_resume(RESUME_STATE eResumeSetVal) { } #define SUSPEND_ENABLED 1 -void __irq_usb_lp_can_rx0(void) { +__weak void __irq_usb_lp_can_rx0(void) { uint16 istr = USB_BASE->ISTR; /* Use USB_ISR_MSK to only include code for bits we care about. */ @@ -268,6 +274,7 @@ static void handle_out0(void); static void dispatch_ctr_lp() { uint16 istr; + while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) { /* TODO WTF, figure this out: RM0008 says CTR is read-only, * but ST's firmware claims it's clear-only, and emphasizes @@ -288,6 +295,7 @@ static void dispatch_ctr_lp() { } } + /* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's * code, and is ugly/confusing in its use of SaveRState/SaveTState. * Fixing this requires filling in handle_in0(), handle_setup0(), diff --git a/STM32F1/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c b/STM32F1/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c index 7a5a772..dbf82c1 100644 --- a/STM32F1/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c +++ b/STM32F1/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c @@ -62,8 +62,8 @@ #if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \ defined(BOARD_maple_mini) || defined(BOARD_maple_native)) -#warning USB CDC ACM relies on LeafLabs board-specific configuration.\ - You may have problems on non-LeafLabs boards. +//#warning USB CDC ACM relies on LeafLabs board-specific configuration. +// You may have problems on non-LeafLabs boards. #endif static void vcomDataTxCb(void); @@ -80,7 +80,6 @@ static uint8* usbGetConfigDescriptor(uint16 length); static uint8* usbGetStringDescriptor(uint16 length); static void usbSetConfiguration(void); static void usbSetDeviceAddress(void); - /* * Descriptors */ @@ -384,10 +383,16 @@ void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) { /* Present ourselves to the host. Writing 0 to "disc" pin must * pull USB_DP pin up while leaving USB_DM pulled down by the * transceiver. See USB 2.0 spec, section 7.1.7.3. */ - gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP); - gpio_write_bit(disc_dev, disc_bit, 0); - + + if (disc_dev!=NULL) + { + gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP); + gpio_write_bit(disc_dev, disc_bit, 0); + } + /* Initialize the USB peripheral. */ + /* One of the callbacks that will automatically happen from this will be to usbInit(), + which will power up the USB peripheral. */ usb_init_usblib(USBLIB, ep_int_in, ep_int_out); } @@ -395,7 +400,13 @@ void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) { /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0 * spec, section 7.1.7.3). */ nvic_irq_disable(NVIC_USB_LP_CAN_RX0); - gpio_write_bit(disc_dev, disc_bit, 1); + if (disc_dev!=NULL) + { + gpio_write_bit(disc_dev, disc_bit, 1); + } + /* Powerdown the USB peripheral. It gets powered up again with usbInit(), which + gets called when usb_cdcacm_enable() is called. */ + usb_power_off(); } void usb_cdcacm_putc(char ch) { @@ -445,6 +456,11 @@ uint8 usb_cdcacm_is_transmitting(void) { return ( transmitting>0 ? transmitting : 0); } +int usb_cdcacm_tx_available() +{ + return CDC_SERIAL_TX_BUFFER_SIZE - usb_cdcacm_get_pending() - 1; +} + uint16 usb_cdcacm_get_pending(void) { return (tx_head - tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; } @@ -637,7 +653,8 @@ static uint8* vcomGetSetLineCoding(uint16 length) { static void usbInit(void) { pInformation->Current_Configuration = 0; - USB_BASE->CNTR = USB_CNTR_FRES; + // Reset and power up the peripheral. + USB_BASE->CNTR = USB_CNTR_FRES; USBLIB->irq_mask = 0; USB_BASE->CNTR = USBLIB->irq_mask; diff --git a/STM32F1/cores/maple/libmaple/util.c b/STM32F1/cores/maple/libmaple/util.c index 4c0b2c8..f488ea4 100644 --- a/STM32F1/cores/maple/libmaple/util.c +++ b/STM32F1/cores/maple/libmaple/util.c @@ -88,7 +88,7 @@ void _fail(const char* file, int line, const char* exp) { * Provide an __assert_func handler to libc so that calls to assert() * get redirected to _fail. */ -void __assert_func(const char* file, int line, const char* method, +void __assert_func(const char* file, int line, const char* method __attribute__((unused)), const char* expression) { _fail(file, line, expression); } diff --git a/STM32F1/cores/maple/sdio.cpp b/STM32F1/cores/maple/sdio.cpp new file mode 100644 index 0000000..23dfa4e --- /dev/null +++ b/STM32F1/cores/maple/sdio.cpp @@ -0,0 +1,219 @@ +/****************************************************************************** + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/sdio.c + * @author stevstrong + * @brief Secure digital input/output interface. + */ + +#include +#include +#include +#include "wirish.h" + + +//#include +//#include +//#include +//#include "wirish.h" +//#include "boards.h" +// + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + +sdio_dev * SDIO = SDIO_BASE; + +#define DELAY_LONG 20 +#define DELAY_SHORT 2 + +uint8_t dly = DELAY_LONG; // microseconds delay after accessing registers + +/* + * SDIO convenience routines + */ +void sdio_gpios_init(void) +{ + gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_AF_OUTPUT_PP); +/* gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_AF_OUTPUT_PP); +*/ + gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_AF_OUTPUT_PP); + /* + * Todo just remove it, not needed for F1. + */ + /* + gpio_set_af_mode(BOARD_SDIO_D0, 12); + gpio_set_af_mode(BOARD_SDIO_D1, 12); + gpio_set_af_mode(BOARD_SDIO_D2, 12); + gpio_set_af_mode(BOARD_SDIO_D3, 12); + gpio_set_af_mode(BOARD_SDIO_CLK, 12); + gpio_set_af_mode(BOARD_SDIO_CMD, 12); + */ +} + +void sdio_gpios_deinit(void) +{ + gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_INPUT_PU); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_INPUT_PU); + + /* + * Todo just remove it, not needed for F1. + */ + /* + gpio_set_af_mode(BOARD_SDIO_D0, 0); + gpio_set_af_mode(BOARD_SDIO_D1, 0); + gpio_set_af_mode(BOARD_SDIO_D2, 0); + gpio_set_af_mode(BOARD_SDIO_D3, 0); + gpio_set_af_mode(BOARD_SDIO_CLK, 0); + gpio_set_af_mode(BOARD_SDIO_CMD, 0); + */ +} + +/** + * @brief Initialize and reset the SDIO device. + */ +void sdio_init(void) +{ + rcc_clk_enable(RCC_SDIO); + rcc_reset_dev(RCC_SDIO); +} + +void sdio_power_on(void) +{ + SDIO->POWER = SDIO_POWER_PWRCTRL_ON; +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. + delay_us(DELAY_LONG); +} + +void sdio_power_off(void) +{ + SDIO->POWER = SDIO_POWER_PWRCTRL_OFF; +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. + delay_us(DELAY_LONG); +} + +void sdio_set_clock(uint32_t clk) +{ + /* + * limit the SDIO master clock to 8/3 of PCLK2.See RM 22.3 + * Also limited to no more than 48Mhz + */ + clk = min(clk,(SDIOCLK/3)*8); + clk = min(clk,36000000); + + if (clk<1000000) dly = DELAY_LONG; + else dly = DELAY_SHORT; + + /* + * round up divider, so we don't run the card over the speed supported. + + */ + uint32 div = SDIOCLK/clk + (SDIOCLK % clk != 0) - 2; + + + sdio_disable(); + //Serial.println(div,DEC); + SDIO->CLKCR = (SDIO->CLKCR & (~(SDIO_CLKCR_CLKDIV|SDIO_CLKCR_BYPASS))) | SDIO_CLKCR_PWRSAV | SDIO_CLKCR_HWFC_EN | SDIO_CLKCR_CLKEN | (div & SDIO_CLKCR_CLKDIV); + delay_us(dly); +} + +void sdio_set_dbus_width(uint16_t bus_w) +{ + SDIO->CLKCR = (SDIO->CLKCR & (~SDIO_CLKCR_WIDBUS)) | bus_w; + gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_AF_OUTPUT_PP); + delay_us(dly); +} + +void sdio_set_dblock_size(uint8_t dbsize) +{ + SDIO->DCTRL = (SDIO->DCTRL&(~SDIO_DCTRL_DBLOCKSIZE)) | ((dbsize&0xF)<<4); + delay_us(dly); +} + +void sdio_enable(void) +{ + SDIO->CLKCR |= SDIO_CLKCR_CLKEN; + delay_us(dly); +} + +void sdio_disable(void) +{ + SDIO->CLKCR ^= SDIO_CLKCR_CLKEN; + delay_us(dly); +} + +/** + * @brief Configure and enable the SDIO device. + */ +void sdio_begin(void) +{ + + sdio_init(); + sdio_power_on(); + sdio_gpios_init(); + // Set initial SCK rate. + sdio_set_clock(400000); + delay_us(200); // generate 80 pulses at 400kHz +} + +/** + * @brief Disables the SDIO device. + */ +void sdio_end(void) +{ + while ( sdio_cmd_xfer_ongoing() ); + sdio_disable(); + sdio_gpios_deinit(); + sdio_power_off(); + rcc_clk_disable(RCC_SDIO); +} + +/** + * @brief Send command by the SDIO device. + */ +uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg) +{ + uint8_t retries = 10; // in case of errors + do { // retry command if errors detected + // clear interrupt flags - IMPORTANT!!! + SDIO->ICR = SDIO_ICR_CMD_FLAGS; + // write command + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)(SDIO_CMD_CPSMEN | cmd_index_resp_type ); + while ( (SDIO->STA&SDIO_STA_CMDACT) ) ; // wait for actual command transfer to finish + // wait for response, if the case + if ( cmd_index_resp_type&(SDIO_CMD_WAIT_SHORT_RESP|SDIO_CMD_WAIT_LONG_RESP) ) { + while ( !(SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CMD_ERROR_FLAGS)) ) ; + } else break; // no response required + if ( SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CTIMEOUT) ) + break; // response received or timeout + // ignore CRC error for CMD5 and ACMD41 + if ( ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==5) || ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==41) ) + break; + } while ( (--retries) ); + return (uint8_t)retries; +} + +#endif // defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) diff --git a/STM32F1/cores/maple/stm32f1/wiring_pulse_f1.cpp b/STM32F1/cores/maple/stm32f1/wiring_pulse_f1.cpp index 9ca4d7f..bb7e2ad 100644 --- a/STM32F1/cores/maple/stm32f1/wiring_pulse_f1.cpp +++ b/STM32F1/cores/maple/stm32f1/wiring_pulse_f1.cpp @@ -1,5 +1,6 @@ #include #include "boards.h" +#include "variant.h" /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds @@ -28,13 +29,13 @@ */ uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout ) { - // cache the port and bit of the pin in order to speed up the + // cache the IDR address and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. - gpio_dev *dev=PIN_MAP[pin].gpio_device; - uint32_t bit = (1U << PIN_MAP[pin].gpio_bit); - + __IO uint32_t * const idr = portInputRegister(digitalPinToPort(pin)); + const uint32_t bit = digitalPinToBitMask(pin); + const uint32_t stateMask = (state ? bit:0); uint32_t width = 0; // keep initialization out of time critical area @@ -45,23 +46,23 @@ uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout ) volatile uint32_t dummyWidth=0; // wait for any previous pulse to end - while ( (dev->regs->IDR & bit) == bit) { + while ((*idr & bit) == stateMask) { if (numloops++ == maxloops) { return 0; } - dummyWidth++; + dummyWidth++; } // wait for the pulse to start - while ((dev->regs->IDR & bit) != bit) { + while ((*idr & bit) != stateMask) { if (numloops++ == maxloops) { return 0; } - dummyWidth++; + dummyWidth++; } // wait for the pulse to stop - while ((dev->regs->IDR & bit) == bit) { + while ((*idr & bit) == stateMask) { if (numloops++ == maxloops) { return 0; } diff --git a/STM32F1/cores/maple/stm32f1/wirish_debug.cpp b/STM32F1/cores/maple/stm32f1/wirish_debug.cpp index f057616..8f6cc98 100644 --- a/STM32F1/cores/maple/stm32f1/wirish_debug.cpp +++ b/STM32F1/cores/maple/stm32f1/wirish_debug.cpp @@ -37,5 +37,5 @@ void disableDebugPorts(void) { } void enableDebugPorts(void) { - afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); + afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY); } diff --git a/STM32F1/cores/maple/stm32f1/wirish_digital_f1.cpp b/STM32F1/cores/maple/stm32f1/wirish_digital_f1.cpp index f16181d..3ea5ed0 100644 --- a/STM32F1/cores/maple/stm32f1/wirish_digital_f1.cpp +++ b/STM32F1/cores/maple/stm32f1/wirish_digital_f1.cpp @@ -80,10 +80,13 @@ void pinMode(uint8 pin, WiringPinMode mode) { gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); if (PIN_MAP[pin].timer_device != NULL) { - /* Enable/disable timer channels if we're switching into or - * out of PWM. */ + if ( pwm ) { // we're switching into PWM, enable timer channels timer_set_mode(PIN_MAP[pin].timer_device, PIN_MAP[pin].timer_channel, - pwm ? TIMER_PWM : TIMER_DISABLED); + TIMER_PWM ); + } else { // disable channel output in non pwm-Mode + timer_cc_disable(PIN_MAP[pin].timer_device, + PIN_MAP[pin].timer_channel); + } } } diff --git a/STM32F1/cores/maple/tone.cpp b/STM32F1/cores/maple/tone.cpp index 965bfdd..c179c34 100644 --- a/STM32F1/cores/maple/tone.cpp +++ b/STM32F1/cores/maple/tone.cpp @@ -60,7 +60,7 @@ uint8_t tone_ntimer = TONE_TIMER; // timer used to generate freque bool tone_state = true; // last pin state for toggling short tone_pin = -1; // pin for outputting sound short tone_freq = 444; // tone frequency (0=pause) -uint32_t tone_nhw = 0; // tone duration in number of half waves +volatile uint32_t tone_nhw = 0; // tone duration in number of half waves uint16_t tone_tcount = 0; // time between handler calls in 1/36 usec uint16_t tone_ncount = 0; // handler call between toggling uint16_t tone_n = 0; // remaining handler calls before toggling @@ -146,12 +146,12 @@ void tone(uint32_t pin, uint32_t freq, uint32_t duration) { tone_timer->pause(); - if(freq > 0 && duration >0 ){ + if(freq > 0){ uint32_t count = (F_CPU/4)/freq; // timer counts per half wave tone_ncount = tone_n = (count>>16)+1; // number of 16-bit count chunk tone_tcount = count/tone_ncount; // size of count chunk if(duration > 0) // number of half waves to be generated - tone_nhw = ((duration*(freq>0?freq:100))/1000)<<1; + tone_nhw = duration*freq*2/1000; else // no duration specified, continuous sound until noTone() called tone_nhw = 0; @@ -186,6 +186,8 @@ void tone(uint32_t pin, uint32_t freq, uint32_t duration) { pinMode(tone_pin, INPUT); } + + //while(tone_nhw) ; // blocks till duration elapsed } //////////////////////////////////////////////////////////////////////////////// diff --git a/STM32F1/cores/maple/usb_serial.cpp b/STM32F1/cores/maple/usb_serial.cpp index 5eaf70e..1cca589 100644 --- a/STM32F1/cores/maple/usb_serial.cpp +++ b/STM32F1/cores/maple/usb_serial.cpp @@ -37,7 +37,7 @@ #include #include #include - +#include #include "wirish.h" /* @@ -54,6 +54,9 @@ static void ifaceSetupHook(unsigned, void*); */ #define USB_TIMEOUT 50 +#if BOARD_HAVE_SERIALUSB +bool USBSerial::_hasBegun = false; +#endif USBSerial::USBSerial(void) { #if !BOARD_HAVE_SERIALUSB @@ -62,8 +65,13 @@ USBSerial::USBSerial(void) { } void USBSerial::begin(void) { + #if BOARD_HAVE_SERIALUSB - usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); + if (_hasBegun) + return; + _hasBegun = true; + + usb_cdcacm_enable(BOARD_USB_DISC_DEV, (uint8_t)BOARD_USB_DISC_BIT); usb_cdcacm_set_hooks(USB_CDCACM_HOOK_RX, rxHook); usb_cdcacm_set_hooks(USB_CDCACM_HOOK_IFACE_SETUP, ifaceSetupHook); #endif @@ -75,6 +83,7 @@ void USBSerial::begin(unsigned long ignoreBaud) volatile unsigned long removeCompilerWarningsIgnoreBaud=ignoreBaud; ignoreBaud=removeCompilerWarningsIgnoreBaud; + begin(); } void USBSerial::begin(unsigned long ignoreBaud, uint8_t ignore) { @@ -83,13 +92,16 @@ volatile uint8_t removeCompilerWarningsIgnore=ignore; ignoreBaud=removeCompilerWarningsIgnoreBaud; ignore=removeCompilerWarningsIgnore; + begin(); } void USBSerial::end(void) { #if BOARD_HAVE_SERIALUSB - usb_cdcacm_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); + usb_cdcacm_disable(BOARD_USB_DISC_DEV, (uint8_t)BOARD_USB_DISC_BIT); usb_cdcacm_remove_hooks(USB_CDCACM_HOOK_RX | USB_CDCACM_HOOK_IFACE_SETUP); + _hasBegun = false; #endif + } size_t USBSerial::write(uint8 ch) { @@ -107,7 +119,7 @@ size_t n = 0; size_t USBSerial::write(const uint8 *buf, uint32 len) { size_t n = 0; - if (!this->isConnected() || !buf) { + if (!(bool) *this || !buf) { return 0; } @@ -136,6 +148,8 @@ int USBSerial::peek(void) } } +int USBSerial::availableForWrite(void) { return usb_cdcacm_tx_available(); } + void USBSerial::flush(void) { /*Roger Clark. Rather slow method. Need to improve this */ @@ -156,6 +170,19 @@ uint32 USBSerial::read(uint8 * buf, uint32 len) { return rxed; } +size_t USBSerial::readBytes(char *buf, const size_t& len) +{ + size_t rxed=0; + unsigned long startMillis; + startMillis = millis(); + if (len <= 0) return 0; + do { + rxed += usb_cdcacm_rx((uint8 *)buf + rxed, len - rxed); + if (rxed == len) return rxed; + } while(millis() - startMillis < _timeout); + return rxed; +} + /* Blocks forever until 1 byte is received */ int USBSerial::read(void) { uint8 b; @@ -178,10 +205,6 @@ uint8 USBSerial::pending(void) { return usb_cdcacm_get_pending(); } -uint8 USBSerial::isConnected(void) { - return usb_is_connected(USBLIB) && usb_is_configured(USBLIB) && usb_cdcacm_get_dtr(); -} - uint8 USBSerial::getDTR(void) { return usb_cdcacm_get_dtr(); } @@ -190,6 +213,10 @@ uint8 USBSerial::getRTS(void) { return usb_cdcacm_get_rts(); } +USBSerial::operator bool() { + return usb_is_connected(USBLIB) && usb_is_configured(USBLIB) && usb_cdcacm_get_dtr(); +} + #if BOARD_HAVE_SERIALUSB #ifdef SERIAL_USB USBSerial Serial; @@ -211,7 +238,7 @@ enum reset_state_t { static reset_state_t reset_state = DTR_UNSET; -static void ifaceSetupHook(unsigned hook, void *requestvp) { +static void ifaceSetupHook(unsigned hook __attribute__((unused)), void *requestvp) { uint8 request = *(uint8*)requestvp; // Ignore requests we're not interested in. @@ -238,20 +265,12 @@ static void ifaceSetupHook(unsigned hook, void *requestvp) { break; } #endif - -#if defined(BOOTLOADER_robotis) - uint8 dtr = usb_cdcacm_get_dtr(); - uint8 rts = usb_cdcacm_get_rts(); - - if (rts && !dtr) { - reset_state = DTR_NEGEDGE; - } -#endif - +#if false if ((usb_cdcacm_get_baud() == 1200) && (reset_state == DTR_NEGEDGE)) { iwdg_init(IWDG_PRE_4, 10); while (1); } +#endif } #define RESET_DELAY 100000 @@ -262,41 +281,40 @@ static void wait_reset(void) { } #endif + #define STACK_TOP 0x20000800 #define EXC_RETURN 0xFFFFFFF9 #define DEFAULT_CPSR 0x61000000 -static void rxHook(unsigned hook, void *ignored) { +static void rxHook(unsigned hook __attribute__((unused)), void *ignored __attribute__((unused))) { +static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; /* FIXME this is mad buggy; we need a new reset sequence. E.g. NAK * after each RX means you can't reset if any bytes are waiting. */ if (reset_state == DTR_NEGEDGE) { - reset_state = DTR_LOW; - - if (usb_cdcacm_data_available() >= 4) { - // The magic reset sequence is "1EAF". -#ifdef SERIAL_USB - static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; -#else - #if defined(BOOTLOADER_robotis) - static const uint8 magic[4] = {'C', 'M', '9', 'X'}; - #else - static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; - #endif -#endif + if (usb_cdcacm_data_available() >= 4) + { uint8 chkBuf[4]; // Peek at the waiting bytes, looking for reset sequence, // bailing on mismatch. usb_cdcacm_peek_ex(chkBuf, usb_cdcacm_data_available() - 4, 4); for (unsigned i = 0; i < sizeof(magic); i++) { - if (chkBuf[i] != magic[i]) { + if (chkBuf[i] != magic[i]) + { + reset_state = DTR_LOW; return; } } #ifdef SERIAL_USB + // The magic reset sequence is "1EAF". // Got the magic sequence -> reset, presumably into the bootloader. // Return address is wait_reset, but we must set the thumb bit. + bkp_init(); + bkp_enable_writes(); + bkp_write(10, 0x424C); + bkp_disable_writes(); + uintptr_t target = (uintptr_t)wait_reset | 0x1; asm volatile("mov r0, %[stack_top] \n\t" // Reset stack "mov sp, r0 \n\t" @@ -320,15 +338,9 @@ static void rxHook(unsigned hook, void *ignored) { [cpsr] "r" (DEFAULT_CPSR) : "r0", "r1", "r2"); #endif - -#if defined(BOOTLOADER_robotis) - iwdg_init(IWDG_PRE_4, 10); -#endif - /* Can't happen. */ ASSERT_FAULT(0); } } } - -#endif // BOARD_HAVE_SERIALUSB +#endif // BOARD_HAVE_SERIALUSB \ No newline at end of file diff --git a/STM32F1/cores/maple/usb_serial.h b/STM32F1/cores/maple/usb_serial.h index 96bbefc..8351593 100644 --- a/STM32F1/cores/maple/usb_serial.h +++ b/STM32F1/cores/maple/usb_serial.h @@ -44,38 +44,51 @@ public: void begin(void); - // Roger Clark. Added dummy function so that existing Arduino sketches which specify baud rate will compile. - void begin(unsigned long); - void begin(unsigned long, uint8_t); + // Roger Clark. Added dummy function so that existing Arduino sketches which specify baud rate will compile. + void begin(unsigned long); + void begin(unsigned long, uint8_t); void end(void); - operator bool() { return true; } // Roger Clark. This is needed because in cardinfo.ino it does if (!Serial) . It seems to be a work around for the Leonardo that we needed to implement just to be compliant with the API - virtual int available(void);// Changed to virtual + size_t readBytes(char *buf, const size_t& len); uint32 read(uint8 * buf, uint32 len); - // uint8 read(void); + // uint8 read(void); - // Roger Clark. added functions to support Arduino 1.0 API + // Roger Clark. added functions to support Arduino 1.0 API virtual int peek(void); virtual int read(void); int availableForWrite(void); virtual void flush(void); - - + + size_t write(uint8); size_t write(const char *str); size_t write(const uint8*, uint32); uint8 getRTS(); uint8 getDTR(); - uint8 isConnected(); uint8 pending(); + + /* SukkoPera: This is the Arduino way to check if an USB CDC serial + * connection is open. + + * Used for instance in cardinfo.ino. + */ + operator bool(); + + /* Old libmaple way to check for serial connection. + * + * Deprecated, use the above. + */ + uint8 isConnected() __attribute__((deprecated("Use !Serial instead"))) { return (bool) *this; } + +protected: + static bool _hasBegun; }; -#ifdef SERIAL_USB - extern USBSerial Serial; +#ifdef SERIAL_USB + extern USBSerial Serial; #endif #endif - diff --git a/STM32F1/cores/maple/wirish.h b/STM32F1/cores/maple/wirish.h index 3ffee83..eb07c77 100644 --- a/STM32F1/cores/maple/wirish.h +++ b/STM32F1/cores/maple/wirish.h @@ -104,5 +104,7 @@ typedef unsigned int word; #define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) #define microsecondsToClockCycles(a) ( (a) * (F_CPU / 1000000L) ) +#define digitalPinToInterrupt(pin) (pin) + #endif diff --git a/STM32F1/cores/maple/wirish_math.cpp b/STM32F1/cores/maple/wirish_math.cpp index 3b682d3..f8ada9f 100644 --- a/STM32F1/cores/maple/wirish_math.cpp +++ b/STM32F1/cores/maple/wirish_math.cpp @@ -47,3 +47,12 @@ long random(long howsmall, long howbig) { return random(diff) + howsmall; } +extern uint16_t makeWord( uint16_t w ) +{ + return w ; +} + +extern uint16_t makeWord( uint8_t h, uint8_t l ) +{ + return (h << 8) | l ; +} diff --git a/STM32F1/cores/maple/wirish_math.h b/STM32F1/cores/maple/wirish_math.h index d103d86..b85253f 100644 --- a/STM32F1/cores/maple/wirish_math.h +++ b/STM32F1/cores/maple/wirish_math.h @@ -33,6 +33,7 @@ #define _WIRISH_WIRISH_MATH_H_ #include +#include /** * @brief Initialize the pseudo-random number generator. @@ -78,11 +79,12 @@ long random(long min, long max); * @param toEnd the end of the value's mapped range. * @return the mapped value. */ -static inline long map(long value, long fromStart, long fromEnd, - long toStart, long toEnd) { - return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) + - toStart; -} + // Fix by Pito 9/2017 + static inline int32_t map(int32_t value, int32_t fromStart, int32_t fromEnd, + int32_t toStart, int32_t toEnd) { + return ((int64_t)(value - fromStart) * (toEnd - toStart)) / (fromEnd - fromStart) + + toStart; + } #define PI 3.1415926535897932384626433832795 #define HALF_PI 1.5707963267948966192313216916398 @@ -161,4 +163,9 @@ double sqrt(double x); */ double pow(double x, double y); +extern uint16_t makeWord( uint16_t w ) ; +extern uint16_t makeWord( uint8_t h, uint8_t l ) ; + +#define word(...) makeWord(__VA_ARGS__) + #endif diff --git a/STM32F1/cores/maple/wirish_time.cpp b/STM32F1/cores/maple/wirish_time.cpp index 08fd2d1..6404bec 100644 --- a/STM32F1/cores/maple/wirish_time.cpp +++ b/STM32F1/cores/maple/wirish_time.cpp @@ -32,11 +32,15 @@ #include #include +#include "Arduino.h" void delay(unsigned long ms) { uint32 start = millis(); - while (millis() - start < ms) - ; + do + { + yield(); + } + while (millis() - start < ms); } void delayMicroseconds(uint32 us) { diff --git a/STM32F1/cores/maple/wirish_types.h b/STM32F1/cores/maple/wirish_types.h index 195cda8..14fb692 100644 --- a/STM32F1/cores/maple/wirish_types.h +++ b/STM32F1/cores/maple/wirish_types.h @@ -55,7 +55,6 @@ typedef struct stm32_pin_info { uint8 gpio_bit; /**< Pin's GPIO port bit. */ uint8 timer_channel; /**< Timer channel, or 0 if none. */ uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */ - uint8 pinMode; /**< mode specific by pinMode call (Roger Clark added to optimize compatibility with Arduino API*/ } stm32_pin_info; /** diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Communication/ASCIITable/ASCIITable.ino b/STM32F1/libraries/A_STM32_Examples/examples/Communication/ASCIITable/ASCIITable.ino index fc5e5d7..d647457 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/Communication/ASCIITable/ASCIITable.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/Communication/ASCIITable/ASCIITable.ino @@ -47,7 +47,7 @@ void loop() { // Prints value unaltered, i.e. the raw binary version of the // byte. The serial monitor interprets all bytes as // ASCII, so 33, the first number, will show up as '!' - Serial.print(thisByte, BYTE); + Serial.write(thisByte); Serial.print(", dec: "); // Prints value as string as an ASCII-encoded decimal (base 10). diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Communication/MIDI/Midi.ino b/STM32F1/libraries/A_STM32_Examples/examples/Communication/MIDI/Midi.ino index 820ffdc..4feaea7 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/Communication/MIDI/Midi.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/Communication/MIDI/Midi.ino @@ -44,8 +44,8 @@ void loop() { // Plays a MIDI note. Doesn't check to see that cmd is greater than // 127, or that data values are less than 127: void noteOn(int cmd, int pitch, int velocity) { - Serial1.print(cmd, BYTE); - Serial1.print(pitch, BYTE); - Serial1.print(velocity, BYTE); + Serial1.write(cmd); + Serial1.write(pitch); + Serial1.write(velocity); } diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialCallResponse/SerialCallResponse.ino b/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialCallResponse/SerialCallResponse.ino index eee35e3..81270cf 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialCallResponse/SerialCallResponse.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialCallResponse/SerialCallResponse.ino @@ -50,15 +50,15 @@ void loop() { // read switch, map it to 0 or 255 thirdSensor = map(digitalRead(2), 0, 1, 0, 255); // send sensor values: - Serial.print(firstSensor, BYTE); - Serial.print(secondSensor, BYTE); - Serial.print(thirdSensor, BYTE); + Serial.write(firstSensor); + Serial.write(secondSensor); + Serial.write(thirdSensor); } } void establishContact() { while (Serial.available() <= 0) { - Serial.print('A', BYTE); // send a capital A + Serial.write('A'); // send a capital A delay(300); } } diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialPassthrough/SerialPassthrough.ino b/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialPassthrough/SerialPassthrough.ino index 71b9e34..0d348f8 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialPassthrough/SerialPassthrough.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/Communication/SerialPassthrough/SerialPassthrough.ino @@ -26,6 +26,6 @@ void loop() { // Read from Serial1, send over USB on Maple (or uses hardware serial 1 and hardware serial 2 on non-maple boards: if (Serial1.available()) { inByte = Serial1.read(); - Serial.print(inByte, BYTE); + Serial.write(inByte); } } diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/BlinkNcount/BlinkNcount.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/BlinkNcount/BlinkNcount.ino index 7cabfde..11f88f8 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/BlinkNcount/BlinkNcount.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/BlinkNcount/BlinkNcount.ino @@ -9,27 +9,27 @@ int n = 0; -void setup() { +void setup() { // initialize the digital pin as an output. - pinMode(33, OUTPUT); + pinMode(LED_BUILTIN, OUTPUT); // Initialize virtual COM over USB on Maple Mini Serial.begin(9600); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { - digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off + digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN)); // Turn the LED from off to on, or on to off delay(100); // fast blink } Serial.println("Blink LED & count Demo"); } void loop() { - digitalWrite(33, HIGH); // set the LED on + digitalWrite(LED_BUILTIN, HIGH); // set the LED on delay(500); // wait for a second - digitalWrite(33, LOW); // set the LED off + digitalWrite(LED_BUILTIN, LOW); // set the LED off Serial.print("Loop #: "); n++; Serial.println(n); - - delay(500); // wait + + delay(500); // wait } diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput/IntegerInput.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput/IntegerInput.ino index 55a68e8..4a1d16a 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput/IntegerInput.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput/IntegerInput.ino @@ -18,7 +18,7 @@ void setup() Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART Serial.setTimeout(timeoutPeriod); // default is 1 second // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput_FloatOutput/IntegerInput_FloatOutput.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput_FloatOutput/IntegerInput_FloatOutput.ino index 6f04840..b82394e 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput_FloatOutput/IntegerInput_FloatOutput.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/IntegerInput_FloatOutput/IntegerInput_FloatOutput.ino @@ -19,7 +19,7 @@ void setup() Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART Serial.setTimeout(timeoutPeriod); // default is 1 second // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/InternalTempSensor/InternalTempSensor.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/InternalTempSensor/InternalTempSensor.ino index d6000cd..871ae25 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/InternalTempSensor/InternalTempSensor.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/InternalTempSensor/InternalTempSensor.ino @@ -38,7 +38,7 @@ void setup(void) pinMode(A_RANDOM_ANALOG_PIN, INPUT_ANALOG); // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink @@ -48,7 +48,7 @@ void setup(void) setup_temperature_sensor(); // announce start up - if(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS())) + if(Serial) Serial.println("Temp mon startup"); } @@ -69,7 +69,7 @@ void loop(void) t2 = micros(); vsense = adc_read(ADC1, 16); t3 = micros(); - if(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS())) { + if(Serial) { sprintf(buf,"%04x %08x %04x %08x" , vsense, t3-t2, alogpin, t2-t1); Serial.println(buf); } diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos/PrimeNos.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos/PrimeNos.ino index 09a7a3f..c744219 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos/PrimeNos.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos/PrimeNos.ino @@ -29,7 +29,7 @@ void setup() pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos2/PrimeNos2.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos2/PrimeNos2.ino index 51fe332..a2fd1c9 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos2/PrimeNos2.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos2/PrimeNos2.ino @@ -18,7 +18,7 @@ void setup() { pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos3/PrimeNos3.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos3/PrimeNos3.ino index eec3dc0..8e8fe88 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos3/PrimeNos3.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/PrimeNos3/PrimeNos3.ino @@ -18,7 +18,7 @@ void setup() { pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Binary/Print_Binary.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Binary/Print_Binary.ino index c9c4b88..7409ba5 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Binary/Print_Binary.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Binary/Print_Binary.ino @@ -15,7 +15,7 @@ void setup() pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Float/Print_Float.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Float/Print_Float.ino index 289db9e..4351d31 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Float/Print_Float.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/Print_Float/Print_Float.ino @@ -17,7 +17,7 @@ void setup() // run once, when the sketch starts pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/Print_HEX/Print_HEX.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/Print_HEX/Print_HEX.ino index cfdb977..2dc41fe 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/Print_HEX/Print_HEX.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/Print_HEX/Print_HEX.ino @@ -16,7 +16,7 @@ void setup() // run once, when the sketch starts pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UART // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/SerialReadUntil/SerialReadUntil.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/SerialReadUntil/SerialReadUntil.ino index 1e7d400..80d3b3b 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/SerialReadUntil/SerialReadUntil.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/SerialReadUntil/SerialReadUntil.ino @@ -13,7 +13,7 @@ void setup() { pinMode(33, OUTPUT); Serial.begin(BAUD); // BAUD has no effect on USB serial: placeholder for physical UAR // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/StringEx_Parsing/StringEx_Parsing.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/StringEx_Parsing/StringEx_Parsing.ino index d98193c..fd30b4c 100644 Binary files a/STM32F1/libraries/A_STM32_Examples/examples/General/StringEx_Parsing/StringEx_Parsing.ino and b/STM32F1/libraries/A_STM32_Examples/examples/General/StringEx_Parsing/StringEx_Parsing.ino differ diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/USB_ASCII/USB_ASCII.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/USB_ASCII/USB_ASCII.ino index e38b176..8a6fe53 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/USB_ASCII/USB_ASCII.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/USB_ASCII/USB_ASCII.ino @@ -34,7 +34,7 @@ void setup() { pinMode(33, OUTPUT); Serial.begin(); // USB does not require BAUD // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink @@ -67,7 +67,7 @@ void loop() { // Prints value unaltered, i.e. the raw binary version of the // byte. The serial monitor interprets all bytes as // ASCII, so 33, the first number, will show up as '!' - Serial.print(thisByte, BYTE); + Serial.write(thisByte); Serial.print(", dec: "); // Prints value as string as an ASCII-encoded decimal (base 10). diff --git a/STM32F1/libraries/A_STM32_Examples/examples/General/strtol_DecEquivalents/strtol_DecEquivalents.ino b/STM32F1/libraries/A_STM32_Examples/examples/General/strtol_DecEquivalents/strtol_DecEquivalents.ino index 7d799af..f759471 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/General/strtol_DecEquivalents/strtol_DecEquivalents.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/General/strtol_DecEquivalents/strtol_DecEquivalents.ino @@ -19,7 +19,7 @@ void setup() { pinMode(33, OUTPUT); Serial.begin(9600); // wait for serial monitor to be connected. - while (!(Serial.isConnected() && (Serial.getDTR() || Serial.getRTS()))) + while (!Serial) { digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off delay(100); // fast blink diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Maple/TimerInterrupts/TimerInterrupts.ino b/STM32F1/libraries/A_STM32_Examples/examples/Maple/TimerInterrupts/TimerInterrupts.ino index e973358..38eb7d0 100644 --- a/STM32F1/libraries/A_STM32_Examples/examples/Maple/TimerInterrupts/TimerInterrupts.ino +++ b/STM32F1/libraries/A_STM32_Examples/examples/Maple/TimerInterrupts/TimerInterrupts.ino @@ -32,24 +32,24 @@ void setup() pinMode(BUTTON_PIN, INPUT_PULLUP); // Setup LED Timer - Timer2.setChannel1Mode(TIMER_OUTPUTCOMPARE); + Timer2.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE); Timer2.setPeriod(LED_RATE); // in microseconds - Timer2.setCompare1(1); // overflow might be small - Timer2.attachCompare1Interrupt(handler_led); + Timer2.setCompare(TIMER_CH1, 1); // overflow might be small + Timer2.attachInterrupt(TIMER_CH1, handler_led); // Setup Counting Timers - Timer3.setChannel1Mode(TIMER_OUTPUTCOMPARE); - Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE); + Timer3.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE); + Timer4.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE); Timer3.pause(); Timer4.pause(); Timer3.setCount(0); Timer4.setCount(0); Timer3.setOverflow(30000); Timer4.setOverflow(30000); - Timer3.setCompare1(1000); // somewhere in the middle - Timer4.setCompare1(1000); - Timer3.attachCompare1Interrupt(handler1); - Timer4.attachCompare1Interrupt(handler2); + Timer3.setCompare(TIMER_CH1, 1000); // somewhere in the middle + Timer4.setCompare(TIMER_CH1, 1000); + Timer3.attachInterrupt(TIMER_CH1, handler1); + Timer4.attachInterrupt(TIMER_CH1, handler2); Timer3.resume(); Timer4.resume(); diff --git a/examples/Sensors/HardTimerAsEncoder/HardTimerAsEncoder.ino b/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardTimerAsEncoder/HardTimerAsEncoder.ino similarity index 100% rename from examples/Sensors/HardTimerAsEncoder/HardTimerAsEncoder.ino rename to STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardTimerAsEncoder/HardTimerAsEncoder.ino diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardwareTimerOnePulseMode/HardwareTimerOnePulseMode.ino b/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardwareTimerOnePulseMode/HardwareTimerOnePulseMode.ino new file mode 100644 index 0000000..348e321 --- /dev/null +++ b/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardwareTimerOnePulseMode/HardwareTimerOnePulseMode.ino @@ -0,0 +1,67 @@ +/* + * Example of the Timer Input Capture mode combined with one pulse mode + * + * This example uses: + * - Timer2 channel 1 as capture input + * - Timer2 channel 2 to generate the pulses, + * - Timer 3 to generate a PWM trigger signal for capture input + */ + +#include + +const uint16_t pulseDelay = 200; +const uint16_t pulseWidth = 200; +//----------------------------------------------------------------------------- +void toggle_led() +{ + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); +} +//----------------------------------------------------------------------------- +void setup() +{ + // setup PA1 (Timer2 channel 2) to PWM (one pulse mode) + pinMode(PA1, PWM); + // setup PA0 (Timer 2 channel 1) as input (capture input mode) + pinMode(PA0, INPUT); + + // stop the timers before configuring them + Timer2.pause(); + + Timer2.setPrescaleFactor(72); // 1 µs resolution + Timer2.setCompare(TIMER_CH2, pulseDelay); + Timer2.setOverflow(pulseWidth + pulseDelay-1); + + // counter setup in one pulse mode, as slave triggered by TI1 + TIMER2_BASE->CR1 = ( TIMER_CR1_OPM ); // one pulse mode + Timer2.setSlaveFlags( TIMER_SMCR_TS_TI1FP1 | TIMER_SMCR_SMS_TRIGGER ); + + // channel 1: capture input on rising edge + Timer2.setMode(TIMER_CH1, TIMER_INPUT_CAPTURE); + //Timer2.setPolarity(TIMER_CH1, 1); // trigger on falling edge + // channel 2: invert polarity (we want low for CNT=1000 ) + { + t = millis(); + toggle_led(); + } +} diff --git a/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardwareTimerPWMInput/HardwareTimerPWMInput.ino b/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardwareTimerPWMInput/HardwareTimerPWMInput.ino new file mode 100644 index 0000000..2cc962a --- /dev/null +++ b/STM32F1/libraries/A_STM32_Examples/examples/Sensors/HardwareTimerPWMInput/HardwareTimerPWMInput.ino @@ -0,0 +1,77 @@ +/* + * Example of the Timer Input Capture mode to measure PWM pulse width and period. + * + * This example uses: + * - Timer2 channel 1 as capture input + * - Timer3 to generate a PWM trigger signal for capture input + */ + +#include + +const uint8_t pwmPulse = 20; // ms +const uint8_t pwmPeriod = 50; // ms +//----------------------------------------------------------------------------- +void toggle_led() +{ + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); +} +//----------------------------------------------------------------------------- +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); + + // setup PA0 (Timer 2 channel 1) as input capture mode + pinMode(PA0, INPUT); + + while (!Serial); delay(1000); + + Serial << "Example of the Timer Input Capture mode to measure PWM pulse width and period\n\n"; + + // stop the timers before configuring them + Timer2.pause(); + Timer3.pause(); + + Timer2.setPrescaleFactor(72); // 1 microsecond resolution + + // setup timer 2 channel 1 capture on rising edge + Timer2.setInputCaptureMode(TIMER_CH1, TIMER_IC_INPUT_DEFAULT); // use default input TI1 + // setup timer 2 channel 2 capture on falling edge + Timer2.setInputCaptureMode(TIMER_CH2, TIMER_IC_INPUT_SWITCH); // use switched input TI1 + Timer2.setPolarity(TIMER_CH2, 1); // trigger on falling edge + + // counter setup as slave triggered by TI1 in reset mode + Timer2.setSlaveFlags( TIMER_SMCR_TS_TI1FP1 | TIMER_SMCR_SMS_RESET ); + + Timer2.refresh(); + Timer2.getCompare(TIMER_CH1); // clear capture flag + Timer2.getCompare(TIMER_CH2); // clear capture flag + Timer2.resume(); // let timer 2 run + + // setup PA6 (Timer3 channel 1) to generate 1 ms period PWM with 10% DC + pinMode(PA6, PWM); + Timer3.setPrescaleFactor(72); // 1 µs resolution + Timer3.setCompare(TIMER_CH1, pwmPulse*1000); + Timer3.setOverflow(pwmPeriod*1000); + Timer3.refresh(); + + Timer3.resume(); // let timer 3 run + + // discard first reading + // wait for first period end + while ( !Timer2.getInputCaptureFlag(TIMER_CH1) ); + Timer2.getCompare(TIMER_CH1); // clear capture flag +} +//----------------------------------------------------------------------------- +void loop() +{ + if ( Timer2.getInputCaptureFlag(TIMER_CH2) ) // high pulse end + { + Serial << "PWM pulse width: " << Timer2.getCompare(TIMER_CH2); + } + if ( Timer2.getInputCaptureFlag(TIMER_CH1) ) // period end + { + Serial << ", period: " << Timer2.getCompare(TIMER_CH1) << endl; + toggle_led(); + //delay(500); // read the values only 2 times per second + } +} diff --git a/STM32F1/libraries/A_STM32_Examples/keywords.txt b/STM32F1/libraries/A_STM32_Examples/keywords.txt index e40a099..c553422 100644 --- a/STM32F1/libraries/A_STM32_Examples/keywords.txt +++ b/STM32F1/libraries/A_STM32_Examples/keywords.txt @@ -10,3 +10,7 @@ # Constants (LITERAL1) ####################################### +OUTPUT_OPEN_DRAIN LITERAL1 +INPUT_ANALOG LITERAL1 +INPUT_PULLDOWN LITERAL1 +PWM LITERAL1 \ No newline at end of file diff --git a/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.cpp b/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.cpp index 333b122..7d561f8 100644 --- a/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.cpp +++ b/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.cpp @@ -59,451 +59,15 @@ POSSIBILITY OF SUCH DAMAGE. #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #endif -Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): - WIDTH(w), HEIGHT(h) +Adafruit_GFX_AS::Adafruit_GFX_AS(int16_t w, int16_t h): Adafruit_GFX(w, h) { - _width = WIDTH; - _height = HEIGHT; - rotation = 0; - cursor_y = cursor_x = 0; - textsize = 1; - textcolor = textbgcolor = 0xFFFF; - wrap = true; -} - -// Draw a circle outline -void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, - uint16_t color) { - int16_t f = 1 - r; - int16_t ddF_x = 1; - int16_t ddF_y = -2 * r; - int16_t x = 0; - int16_t y = r; - - drawPixel(x0 , y0+r, color); - drawPixel(x0 , y0-r, color); - drawPixel(x0+r, y0 , color); - drawPixel(x0-r, y0 , color); - - while (x= 0) { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - - drawPixel(x0 + x, y0 + y, color); - drawPixel(x0 - x, y0 + y, color); - drawPixel(x0 + x, y0 - y, color); - drawPixel(x0 - x, y0 - y, color); - drawPixel(x0 + y, y0 + x, color); - drawPixel(x0 - y, y0 + x, color); - drawPixel(x0 + y, y0 - x, color); - drawPixel(x0 - y, y0 - x, color); - } -} - -void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, - int16_t r, uint8_t cornername, uint16_t color) { - int16_t f = 1 - r; - int16_t ddF_x = 1; - int16_t ddF_y = -2 * r; - int16_t x = 0; - int16_t y = r; - - while (x= 0) { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - if (cornername & 0x4) { - drawPixel(x0 + x, y0 + y, color); - drawPixel(x0 + y, y0 + x, color); - } - if (cornername & 0x2) { - drawPixel(x0 + x, y0 - y, color); - drawPixel(x0 + y, y0 - x, color); - } - if (cornername & 0x8) { - drawPixel(x0 - y, y0 + x, color); - drawPixel(x0 - x, y0 + y, color); - } - if (cornername & 0x1) { - drawPixel(x0 - y, y0 - x, color); - drawPixel(x0 - x, y0 - y, color); - } - } -} - -void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, - uint16_t color) { - drawFastVLine(x0, y0-r, 2*r+1, color); - fillCircleHelper(x0, y0, r, 3, 0, color); -} - -// Used to do circles and roundrects -void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, - uint8_t cornername, int16_t delta, uint16_t color) { - - int16_t f = 1 - r; - int16_t ddF_x = 1; - int16_t ddF_y = -2 * r; - int16_t x = 0; - int16_t y = r; - - while (x= 0) { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - - if (cornername & 0x1) { - drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); - drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); - } - if (cornername & 0x2) { - drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); - drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); - } - } -} - -// Bresenham's algorithm - thx wikpedia -void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, - int16_t x1, int16_t y1, - uint16_t color) { - int16_t steep = abs(y1 - y0) > abs(x1 - x0); - if (steep) { - swap(x0, y0); - swap(x1, y1); - } - - if (x0 > x1) { - swap(x0, x1); - swap(y0, y1); - } - - int16_t dx, dy; - dx = x1 - x0; - dy = abs(y1 - y0); - - int16_t err = dx / 2; - int16_t ystep; - - if (y0 < y1) { - ystep = 1; - } else { - ystep = -1; - } - - for (; x0<=x1; x0++) { - if (steep) { - drawPixel(y0, x0, color); - } else { - drawPixel(x0, y0, color); - } - err -= dy; - if (err < 0) { - y0 += ystep; - err += dx; - } - } -} - -// Draw a rectangle -void Adafruit_GFX::drawRect(int16_t x, int16_t y, - int16_t w, int16_t h, - uint16_t color) { - drawFastHLine(x, y, w, color); - drawFastHLine(x, y+h-1, w, color); - drawFastVLine(x, y, h, color); - drawFastVLine(x+w-1, y, h, color); -} - -void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, - int16_t h, uint16_t color) { - // Update in subclasses if desired! - drawLine(x, y, x, y+h-1, color); -} - -void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, - int16_t w, uint16_t color) { - // Update in subclasses if desired! - drawLine(x, y, x+w-1, y, color); -} - -void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, - uint16_t color) { - // Update in subclasses if desired! - for (int16_t i=x; i= y1 >= y0) - if (y0 > y1) { - swap(y0, y1); swap(x0, x1); - } - if (y1 > y2) { - swap(y2, y1); swap(x2, x1); - } - if (y0 > y1) { - swap(y0, y1); swap(x0, x1); - } - - if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing - a = b = x0; - if(x1 < a) a = x1; - else if(x1 > b) b = x1; - if(x2 < a) a = x2; - else if(x2 > b) b = x2; - drawFastHLine(a, y0, b-a+1, color); - return; - } - - int16_t - dx01 = x1 - x0, - dy01 = y1 - y0, - dx02 = x2 - x0, - dy02 = y2 - y0, - dx12 = x2 - x1, - dy12 = y2 - y1, - sa = 0, - sb = 0; - - // For upper part of triangle, find scanline crossings for segments - // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 - // is included here (and second loop will be skipped, avoiding a /0 - // error there), otherwise scanline y1 is skipped here and handled - // in the second loop...which also avoids a /0 error here if y0=y1 - // (flat-topped triangle). - if(y1 == y2) last = y1; // Include y1 scanline - else last = y1-1; // Skip it - - for(y=y0; y<=last; y++) { - a = x0 + sa / dy01; - b = x0 + sb / dy02; - sa += dx01; - sb += dx02; - /* longhand: - a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); - b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); - */ - if(a > b) swap(a,b); - drawFastHLine(a, y, b-a+1, color); - } - - // For lower part of triangle, find scanline crossings for segments - // 0-2 and 1-2. This loop is skipped if y1=y2. - sa = dx12 * (y - y1); - sb = dx02 * (y - y0); - for(; y<=y2; y++) { - a = x1 + sa / dy12; - b = x0 + sb / dy02; - sa += dx12; - sb += dx02; - /* longhand: - a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); - b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); - */ - if(a > b) swap(a,b); - drawFastHLine(a, y, b-a+1, color); - } -} - -void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, - const uint8_t *bitmap, int16_t w, int16_t h, - uint16_t color) { - - int16_t i, j, byteWidth = (w + 7) / 8; - - for(j=0; j> (i & 7))) { - drawPixel(x+i, y+j, color); - } - } - } -} - -//#if ARDUINO >= 100 -size_t Adafruit_GFX::write(uint8_t c) { -//#else -//void Adafruit_GFX::write(uint8_t c) { -//#endif - if (c == '\n') { - cursor_y += textsize*8; - cursor_x = 0; - } else if (c == '\r') { - // skip em - } else { - drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); - cursor_x += textsize*6; - if (wrap && (cursor_x > (_width - textsize*6))) { - cursor_y += textsize*8; - cursor_x = 0; - } - } -//#if ARDUINO >= 100 - return 1; -//#endif -} - -// Draw a character -void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, - uint16_t color, uint16_t bg, uint8_t size) { -#ifdef LOAD_GLCD - if((x >= _width) || // Clip right - (y >= _height) || // Clip bottom - ((x + 6 * size - 1) < 0) || // Clip left - ((y + 8 * size - 1) < 0)) // Clip top - return; - - for (int8_t i=0; i<6; i++ ) { - uint8_t line; - if (i == 5) - line = 0x0; - else - line = pgm_read_byte(font+(c*5)+i); - for (int8_t j = 0; j<8; j++) { - if (line & 0x1) { - if (size == 1) // default size - drawPixel(x+i, y+j, color); - else { // big size - fillRect(x+(i*size), y+(j*size), size, size, color); - } - } else if (bg != color) { - if (size == 1) // default size - drawPixel(x+i, y+j, bg); - else { // big size - fillRect(x+i*size, y+j*size, size, size, bg); - } - } - line >>= 1; - } - } -#endif -} - -void Adafruit_GFX::setCursor(int16_t x, int16_t y) { - cursor_x = x; - cursor_y = y; -} - -void Adafruit_GFX::setTextSize(uint8_t s) { - textsize = (s > 0) ? s : 1; -} - -void Adafruit_GFX::setTextColor(uint16_t c) { - // For 'transparent' background, we'll set the bg - // to the same as fg instead of using a flag - textcolor = textbgcolor = c; -} - -void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { - textcolor = c; - textbgcolor = b; -} - -void Adafruit_GFX::setTextWrap(boolean w) { - wrap = w; -} - -uint8_t Adafruit_GFX::getRotation(void) { - return rotation; -} - -void Adafruit_GFX::setRotation(uint8_t x) { - rotation = (x & 3); - switch(rotation) { - case 0: - case 2: - _width = WIDTH; - _height = HEIGHT; - break; - case 1: - case 3: - _width = HEIGHT; - _height = WIDTH; - break; - } -} - -// Return the size of the display (per current rotation) -int16_t Adafruit_GFX::width(void) { - return _width; -} - -int16_t Adafruit_GFX::height(void) { - return _height; -} - -void Adafruit_GFX::invertDisplay(boolean i) { - // Do nothing, must be subclassed if supported } /*************************************************************************************** ** Function name: drawUnicode ** Descriptions: draw a unicode ***************************************************************************************/ -int16_t Adafruit_GFX::drawUnicode(uint16_t uniCode, int16_t x, int16_t y, int16_t size) +int16_t Adafruit_GFX_AS::drawUnicode(uint16_t uniCode, int16_t x, int16_t y, int16_t size) { if (size) uniCode -= 32; @@ -615,7 +179,7 @@ return (width+gap)*textsize; // x + ** Function name: drawNumber unsigned with size ** Descriptions: drawNumber ***************************************************************************************/ -int16_t Adafruit_GFX::drawNumber(long long_num,int16_t poX, int16_t poY, int16_t size) +int16_t Adafruit_GFX_AS::drawNumber(long long_num,int16_t poX, int16_t poY, int16_t size) { char tmp[10]; if (long_num < 0) sprintf(tmp, "%li", long_num); @@ -627,7 +191,7 @@ int16_t Adafruit_GFX::drawNumber(long long_num,int16_t poX, int16_t poY, int16_t ** Function name: drawChar ** Descriptions: draw char ***************************************************************************************/ -int16_t Adafruit_GFX::drawChar(char c, int16_t x, int16_t y, int16_t size) +int16_t Adafruit_GFX_AS::drawChar(char c, int16_t x, int16_t y, int16_t size) { return drawUnicode(c, x, y, size); } @@ -636,7 +200,7 @@ int16_t Adafruit_GFX::drawChar(char c, int16_t x, int16_t y, int16_t size) ** Function name: drawString ** Descriptions: draw string ***************************************************************************************/ -int16_t Adafruit_GFX::drawString(char *string, int16_t poX, int16_t poY, int16_t size) +int16_t Adafruit_GFX_AS::drawString(char *string, int16_t poX, int16_t poY, int16_t size) { int16_t sumX = 0; @@ -654,7 +218,7 @@ int16_t Adafruit_GFX::drawString(char *string, int16_t poX, int16_t poY, int16_t ** Function name: drawCentreString ** Descriptions: draw string across centre ***************************************************************************************/ -int16_t Adafruit_GFX::drawCentreString(char *string, int16_t dX, int16_t poY, int16_t size) +int16_t Adafruit_GFX_AS::drawCentreString(char *string, int16_t dX, int16_t poY, int16_t size) { int16_t sumX = 0; int16_t len = 0; @@ -703,7 +267,7 @@ int16_t Adafruit_GFX::drawCentreString(char *string, int16_t dX, int16_t poY, in ** Function name: drawRightString ** Descriptions: draw string right justified ***************************************************************************************/ -int16_t Adafruit_GFX::drawRightString(char *string, int16_t dX, int16_t poY, int16_t size) +int16_t Adafruit_GFX_AS::drawRightString(char *string, int16_t dX, int16_t poY, int16_t size) { int16_t sumX = 0; int16_t len = 0; @@ -754,7 +318,7 @@ int16_t Adafruit_GFX::drawRightString(char *string, int16_t dX, int16_t poY, int ** Function name: drawFloat ** Descriptions: drawFloat ***************************************************************************************/ -int16_t Adafruit_GFX::drawFloat(float floatNumber, int16_t decimal, int16_t poX, int16_t poY, int16_t size) +int16_t Adafruit_GFX_AS::drawFloat(float floatNumber, int16_t decimal, int16_t poX, int16_t poY, int16_t size) { unsigned long temp=0; float decy=0.0; diff --git a/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.h b/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.h index 974c47c..93055a5 100644 --- a/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.h +++ b/STM32F1/libraries/Adafruit_GFX_AS/Adafruit_GFX_AS.h @@ -1,64 +1,20 @@ -#ifndef _ADAFRUIT_GFX_H -#define _ADAFRUIT_GFX_H +#ifndef _ADAFRUIT_GFX_AS_H +#define _ADAFRUIT_GFX_AS_H #include "Load_fonts.h" -#if ARDUINO >= 100 - #include "Arduino.h" - #include "Print.h" -#else - #include "WProgram.h" -#endif +#include #define swap(a, b) { int16_t t = a; a = b; b = t; } -class Adafruit_GFX : public Print { - - public: - - Adafruit_GFX(int16_t w, int16_t h); // Constructor - - // This MUST be defined by the subclass: - virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; - - // These MAY be overridden by the subclass to provide device-specific - // optimized code. Otherwise 'generic' versions are used. - virtual void - drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color), - drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), - drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), - drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), - fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), - fillScreen(uint16_t color), - invertDisplay(boolean i); - - // These exist only with Adafruit_GFX (no subclass overrides) - void - drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), - drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, - uint16_t color), - fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), - fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, - int16_t delta, uint16_t color), - drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, - int16_t x2, int16_t y2, uint16_t color), - fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, - int16_t x2, int16_t y2, uint16_t color), - drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, - int16_t radius, uint16_t color), - fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, - int16_t radius, uint16_t color), - drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, - int16_t w, int16_t h, uint16_t color), - drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, - uint16_t bg, uint8_t size), - setCursor(int16_t x, int16_t y), - setTextColor(uint16_t c), - setTextColor(uint16_t c, uint16_t bg), - setTextSize(uint8_t s), - setTextWrap(boolean w), - setRotation(uint8_t r); - +/** This class provides a few extensions to Adafruit_GFX, mostly for compatibility with + * existing code. Note that the fonts ("size" parameter) are not the same ones use as the + * ones provided by Adafruit_GFX. Using any of the functions defined in this class will + * therefore pull additional font tables into flash. If that is an issue, try to stick + * to the base class, or trim down the fonts loaded in Load_fonts.h . */ +class Adafruit_GFX_AS : public Adafruit_GFX { +public: + Adafruit_GFX_AS(int16_t w, int16_t h); // Constructor int16_t drawUnicode(uint16_t uniCode, int16_t x, int16_t y, int16_t size); int16_t drawNumber(long long_num,int16_t poX, int16_t poY, int16_t size); int16_t drawChar(char c, int16_t x, int16_t y, int16_t size); @@ -66,32 +22,6 @@ class Adafruit_GFX : public Print { int16_t drawCentreString(char *string, int16_t dX, int16_t poY, int16_t size); int16_t drawRightString(char *string, int16_t dX, int16_t poY, int16_t size); int16_t drawFloat(float floatNumber,int16_t decimal,int16_t poX, int16_t poY, int16_t size); - -#if ARDUINO >= 100 - virtual size_t write(uint8_t); -#else - virtual void write(uint8_t); -#endif - - int16_t - height(void), - width(void); - - uint8_t getRotation(void); - - protected: - const int16_t - WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes - int16_t - _width, _height, // Display w/h as modified by current rotation - cursor_x, cursor_y; - uint16_t - textcolor, textbgcolor; - uint8_t - textsize, - rotation; - boolean - wrap; // If set, 'wrap' text at right edge of display }; -#endif // _ADAFRUIT_GFX_H +#endif // _ADAFRUIT_GFX_AS_H diff --git a/STM32F1/libraries/Adafruit_GFX_AS/README.txt b/STM32F1/libraries/Adafruit_GFX_AS/README.txt index 43cf08a..f5ccf00 100644 --- a/STM32F1/libraries/Adafruit_GFX_AS/README.txt +++ b/STM32F1/libraries/Adafruit_GFX_AS/README.txt @@ -1,14 +1,22 @@ -This library has minor modifications to support STM32. -It also was modified to include additional fonts. +This library adds a few font-related functions on top of the Adafruit_GFX library (which you need to install, separately). -This is the core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.). It needs to be paired with a hardware-specific library for each display device we carry (to handle the lower-level functions). +Historically, Adafruit_GFX_AS started as a fork of Adafruit_GFX. Most importantly, it added support for using additional fonts, +before similar functionality became available in Adafruit_GFX. + +Today, the main point of this library is to continue supporting projects that have made use of the functions added in Adafruit_GFX_AS, +while also being fully compatible with Adafruit_GFX (which is used as the base class). It is not recommended to use the functions +provided by the Adafruit_GFX_AS class in newly developed code. + +To use this library with a driver that is not based on Adafruit_GFX_AS, all you will have to do is to replace "Adafrui_GFX" with "Adafruit_GFX_AS" +in your driver code. This will usually be three places: The #include-directive, the base-class declaration, and the call to the base-contstructor. Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! -Written by Limor Fried/Ladyada for Adafruit Industries. +Adafruit_GFX Written by Limor Fried/Ladyada for Adafruit Industries. +Adafruit_GFX_AS funtions added by "Bodmer"(?) BSD license, check license.txt for more information. All text above must be included in any redistribution. -To download, click the DOWNLOAD ZIP button, uncompress and rename the uncompressed folder Adafruit_GFX. Confirm that the Adafruit_GFX folder contains Adafruit_GFX.cpp and Adafruit_GFX.h +To download, click the DOWNLOAD ZIP button, uncompress and rename the uncompressed folder Adafruit_GFX_AS. Confirm that the Adafruit_GFX_AS folder contains Adafruit_GFX_AS.cpp and Adafruit_GFX_AS.h -Place the Adafruit_GFX library folder your /Libraries/ folder. You may need to create the Libraries subfolder if its your first library. Restart the IDE. +Place the Adafruit_GFX_AS library folder your /Libraries/ folder. You may need to create the Libraries subfolder if its your first library. Restart the IDE. diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp index e21f33c..20d434f 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp @@ -4,120 +4,27 @@ This library has been modified for the Maple Mini. Includes DMA transfers on DMA1 CH2 and CH3. */ #include -#include -#include -#include -#include "pins_arduino.h" -#include "wiring_private.h" -#include // Using library SPI in folder: D:\Documents\Arduino\hardware\STM32\STM32F1XX\libraries\SPI - - -// Constructor when using software SPI. All output pins are configurable. -Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t mosi, - int8_t sclk, int8_t rst, int8_t miso) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) { - _cs = cs; - _dc = dc; - _mosi = mosi; - _miso = miso; - _sclk = sclk; - _rst = rst; - hwSPI = false; -} // Constructor when using hardware SPI. Faster, but must use SPI pins // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.) -Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) { +Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX_AS(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) +{ _cs = cs; _dc = dc; _rst = rst; - hwSPI = true; - _mosi = _sclk = 0; } -void Adafruit_ILI9341_STM::spiwrite(uint8_t c) { - - //Serial.print("0x"); Serial.print(c, HEX); Serial.print(", "); - - if (hwSPI) - { -#if defined (__AVR__) - uint8_t backupSPCR = SPCR; - SPCR = mySPCR; - SPDR = c; - while (!(SPSR & _BV(SPIF))); - SPCR = backupSPCR; -#elif defined(TEENSYDUINO) - SPI.transfer(c); -#elif defined (__STM32F1__) - SPI.write(c); -#elif defined (__arm__) - SPI.setClockDivider(11); // 8-ish MHz (full! speed!) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - SPI.transfer(c); - -#endif - } else { - // Fast SPI bitbang swiped from LPD8806 library - for (uint8_t bit = 0x80; bit; bit >>= 1) { - if (c & bit) { - //digitalWrite(_mosi, HIGH); - *mosiport |= mosipinmask; - } else { - //digitalWrite(_mosi, LOW); - *mosiport &= ~mosipinmask; - } - //digitalWrite(_sclk, HIGH); - *clkport |= clkpinmask; - //digitalWrite(_sclk, LOW); - *clkport &= ~clkpinmask; - } - } -} - - -void Adafruit_ILI9341_STM::writecommand(uint8_t c) { - *dcport &= ~dcpinmask; - *csport &= ~cspinmask; - +void Adafruit_ILI9341_STM::writecommand(uint8_t c) +{ + dc_command(); + cs_clear(); spiwrite(c); - - *csport |= cspinmask; + dc_data(); } -void Adafruit_ILI9341_STM::writedata(uint8_t c) { - *dcport |= dcpinmask; - *csport &= ~cspinmask; - - spiwrite(c); - - *csport |= cspinmask; -} - -// If the SPI library has transaction support, these functions -// establish settings and protect from interference from other -// libraries. Otherwise, they simply do nothing. -#ifdef SPI_HAS_TRANSACTION -static inline void spi_begin(void) __attribute__((always_inline)); -static inline void spi_begin(void) { -#ifdef __STM32F1__ - SPI.beginTransaction(SPISettings(36000000, MSBFIRST, SPI_MODE0)); -#else - SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); -#endif -} -static inline void spi_end(void) __attribute__((always_inline)); -static inline void spi_end(void) { - SPI.endTransaction(); -} -#else -#define spi_begin() -#define spi_end() -#endif - // Rather than a bazillion writecommand() and writedata() calls, screen // initialization commands and arguments are organized in these tables // stored in PROGMEM. The table may look bulky, but that's mostly the @@ -128,8 +35,8 @@ static inline void spi_end(void) { // Companion code to the above tables. Reads and issues // a series of LCD commands stored in PROGMEM byte array. -void Adafruit_ILI9341_STM::commandList(uint8_t *addr) { - +void Adafruit_ILI9341_STM::commandList(uint8_t *addr) +{ uint8_t numCommands, numArgs; uint16_t ms; @@ -152,57 +59,24 @@ void Adafruit_ILI9341_STM::commandList(uint8_t *addr) { } -void Adafruit_ILI9341_STM::begin(void) { - if (_rst > 0) { - pinMode(_rst, OUTPUT); - digitalWrite(_rst, LOW); - } - +void Adafruit_ILI9341_STM::begin(SPIClass & spi, uint32_t freq) +{ + mSPI = spi; + _freq = freq; + _safe_freq = (freq>SAFE_FREQ) ? SAFE_FREQ : _freq; pinMode(_dc, OUTPUT); pinMode(_cs, OUTPUT); - csport = portOutputRegister(digitalPinToPort(_cs)); + csport = portSetRegister(_cs); cspinmask = digitalPinToBitMask(_cs); - dcport = portOutputRegister(digitalPinToPort(_dc)); + cs_set(); // deactivate chip + dcport = portSetRegister(_dc); dcpinmask = digitalPinToBitMask(_dc); - if (hwSPI) { // Using hardware SPI -#if defined (__AVR__) - SPI.begin(); - SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (full! speed!) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - mySPCR = SPCR; -#elif defined(TEENSYDUINO) - SPI.begin(); - SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (full! speed!) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); -#elif defined (__STM32F1__) - SPI.begin(); - SPI.setClockDivider(SPI_CLOCK_DIV2); - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - -#elif defined (__arm__) - SPI.begin(); - SPI.setClockDivider(11); // 8-ish MHz (full! speed!) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); -#endif - } else { - pinMode(_sclk, OUTPUT); - pinMode(_mosi, OUTPUT); - pinMode(_miso, INPUT); - clkport = portOutputRegister(digitalPinToPort(_sclk)); - clkpinmask = digitalPinToBitMask(_sclk); - mosiport = portOutputRegister(digitalPinToPort(_mosi)); - mosipinmask = digitalPinToBitMask(_mosi); - *clkport &= ~clkpinmask; - *mosiport &= ~mosipinmask; - } + mSPI.beginTransaction(SPISettings(_safe_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); // toggle RST low to reset if (_rst > 0) { + pinMode(_rst, OUTPUT); digitalWrite(_rst, HIGH); delay(5); digitalWrite(_rst, LOW); @@ -225,7 +99,6 @@ void Adafruit_ILI9341_STM::begin(void) { */ //if(cmdList) commandList(cmdList); - if (hwSPI) spi_begin(); writecommand(0xEF); writedata(0x03); writedata(0x80); @@ -268,7 +141,7 @@ void Adafruit_ILI9341_STM::begin(void) { writedata(0x10); //SAP[2:0];BT[3:0] writecommand(ILI9341_VMCTR1); //VCM control - writedata(0x3e); //�Աȶȵ��� + writedata(0x3e); writedata(0x28); writecommand(ILI9341_VMCTR2); //VCM control2 @@ -330,176 +203,129 @@ void Adafruit_ILI9341_STM::begin(void) { writedata(0x0F); writecommand(ILI9341_SLPOUT); //Exit Sleep - if (hwSPI) spi_end(); delay(120); - if (hwSPI) spi_begin(); writecommand(ILI9341_DISPON); //Display on - if (hwSPI) spi_end(); + delay(120); + cs_set(); + + _width = ILI9341_TFTWIDTH; + _height = ILI9341_TFTHEIGHT; + + mSPI.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT)); } -void Adafruit_ILI9341_STM::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, - uint16_t y1) { -#if defined (__STM32F1__) +void Adafruit_ILI9341_STM::setAddrWindow(uint16_t x0, uint16_t y0, + uint16_t x1, uint16_t y1) +{ writecommand(ILI9341_CASET); // Column addr set - *dcport |= dcpinmask; - *csport &= ~cspinmask; - SPI.setDataSize (SPI_CR1_DFF); - SPI.write(x0); - SPI.write(x1); -// SPI.setDataSize (0); + spiwrite(x0); + spiwrite(x1); writecommand(ILI9341_PASET); // Row addr set - *dcport |= dcpinmask; - *csport &= ~cspinmask; -// SPI.setDataSize (SPI_CR1_DFF); - SPI.write(y0); - SPI.write(y1); - SPI.setDataSize (0); + spiwrite(y0); + spiwrite(y1); writecommand(ILI9341_RAMWR); // write to RAM - -#else - writecommand(ILI9341_CASET); // Column addr set - writedata(x0 >> 8); - writedata(x0 & 0xFF); // XSTART - writedata(x1 >> 8); - writedata(x1 & 0xFF); // XEND - - writecommand(ILI9341_PASET); // Row addr set - writedata(y0 >> 8); - writedata(y0); // YSTART - writedata(y1 >> 8); - writedata(y1); // YEND - - writecommand(ILI9341_RAMWR); // write to RAM -#endif } -void Adafruit_ILI9341_STM::pushColor(uint16_t color) { - if (hwSPI) spi_begin(); - //digitalWrite(_dc, HIGH); - *dcport |= dcpinmask; - //digitalWrite(_cs, LOW); - *csport &= ~cspinmask; +void Adafruit_ILI9341_STM::pushColors(void * colorBuffer, uint16_t nr_pixels, uint8_t async) +{ + cs_clear(); - spiwrite(color >> 8); + if (async==0) { + mSPI.dmaSend(colorBuffer, nr_pixels, 1); + cs_set(); + } else { + mSPI.dmaSendAsync(colorBuffer, nr_pixels, 1); + } +} + +void Adafruit_ILI9341_STM::pushColor(uint16_t color) +{ + cs_clear(); spiwrite(color); - - *csport |= cspinmask; - //digitalWrite(_cs, HIGH); - if (hwSPI) spi_end(); + cs_set(); } -void Adafruit_ILI9341_STM::drawPixel(int16_t x, int16_t y, uint16_t color) { - +void Adafruit_ILI9341_STM::drawPixel(int16_t x, int16_t y, uint16_t color) +{ if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return; - if (hwSPI) spi_begin(); setAddrWindow(x, y, x + 1, y + 1); - *dcport |= dcpinmask; - *csport &= ~cspinmask; - - spiwrite(color >> 8); spiwrite(color); - *csport |= cspinmask; - if (hwSPI) spi_end(); + cs_set(); } void Adafruit_ILI9341_STM::drawFastVLine(int16_t x, int16_t y, int16_t h, - uint16_t color) { - + uint16_t color) +{ // Rudimentary clipping if ((x >= _width) || (y >= _height || h < 1)) return; - if ((y + h - 1) >= _height) h = _height - y; if (h < 2 ) { - drawPixel(x, y, color); - return; + drawPixel(x, y, color); + return; } - // if (hwSPI) spi_begin(); setAddrWindow(x, y, x, y + h - 1); - *dcport |= dcpinmask; - *csport &= ~cspinmask; - -#if defined (__STM32F1__) - SPI.setDataSize (SPI_CR1_DFF); // Set SPI 16bit mode - lineBuffer[0] = color; - SPI.dmaSend(lineBuffer, h, 0); - SPI.setDataSize (0); - #else - uint8_t hi = color >> 8, lo = color; - while (h--) { - spiwrite(hi); - spiwrite(lo); + if (h>DMA_ON_LIMIT) { + lineBuffer[0] = color; + mSPI.dmaSend(lineBuffer, h, 0); + } else { + mSPI.write(color, h); } -#endif - *csport |= cspinmask; + cs_set(); } void Adafruit_ILI9341_STM::drawFastHLine(int16_t x, int16_t y, int16_t w, - uint16_t color) { - - + uint16_t color) +{ // Rudimentary clipping if ((x >= _width) || (y >= _height || w < 1)) return; if ((x + w - 1) >= _width) w = _width - x; if (w < 2 ) { - drawPixel(x, y, color); - return; + drawPixel(x, y, color); + return; } -// if (hwSPI) spi_begin(); setAddrWindow(x, y, x + w - 1, y); - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#if defined (__STM32F1__) - SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode - lineBuffer[0] = color; - SPI.dmaSend(lineBuffer, w, 0); - SPI.setDataSize (0); -#else - uint8_t hi = color >> 8, lo = color; - while (w--) { - spiwrite(hi); - spiwrite(lo); - } -#endif - *csport |= cspinmask; - //digitalWrite(_cs, HIGH); -// if (hwSPI) spi_end(); + if (w>DMA_ON_LIMIT) { + lineBuffer[0] = color; + mSPI.dmaSend(lineBuffer, w, 0); + } else { + mSPI.write(color, w); + } + cs_set(); } -void Adafruit_ILI9341_STM::fillScreen(uint16_t color) { -#if defined (__STM32F1__) - setAddrWindow(0, 0, _width - 1, _height - 1); - *dcport |= dcpinmask; - *csport &= ~cspinmask; - SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode +void Adafruit_ILI9341_STM::fillScreen(uint16_t color) +{ lineBuffer[0] = color; - SPI.dmaSend(lineBuffer, (65535), 0); - SPI.dmaSend(lineBuffer, ((_width * _height) - 65535), 0); - SPI.setDataSize (0); - -#else - fillRect(0, 0, _width, _height, color); -#endif + setAddrWindow(0, 0, _width - 1, _height - 1); + uint32_t nr_bytes = _width * _height; + while ( nr_bytes>65535 ) { + nr_bytes -= 65535; + mSPI.dmaSend(lineBuffer, (65535), 0); + } + mSPI.dmaSend(lineBuffer, nr_bytes, 0); + cs_set(); } // fill a rectangle void Adafruit_ILI9341_STM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, - uint16_t color) { - + uint16_t color) +{ + lineBuffer[0] = color; // rudimentary clipping (drawChar w/big text requires this) if ((x >= _width) || (y >= _height || h < 1 || w < 1)) return; if ((x + w - 1) >= _width) w = _width - x; @@ -508,43 +334,26 @@ void Adafruit_ILI9341_STM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, drawPixel(x, y, color); return; } - - if (hwSPI) spi_begin(); - setAddrWindow(x, y, x + w - 1, y + h - 1); - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#if defined (__STM32F1__) - SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode - lineBuffer[0] = color; - if (w*h <= 65535) { - SPI.dmaSend(lineBuffer, (w*h), 0); - } - else { - SPI.dmaSend(lineBuffer, (65535), 0); - SPI.dmaSend(lineBuffer, ((w*h) - 65535), 0); - } - SPI.setDataSize (0); -#else - uint8_t hi = color >> 8, lo = color; - for(y=h; y>0; y--) - { - for(x=w; x>0; x--) - { - SPI.write(hi); - SPI.write(lo); + setAddrWindow(x, y, x + w - 1, y + h - 1); + uint32_t nr_bytes = w * h; + if ( nr_bytes>DMA_ON_LIMIT ) { + while ( nr_bytes>65535 ) { + nr_bytes -= 65535; + mSPI.dmaSend(lineBuffer, (65535), 0); } + mSPI.dmaSend(lineBuffer, nr_bytes, 0); + } else { + mSPI.write(color, nr_bytes); } -#endif - *csport |= cspinmask; - if (hwSPI) spi_end(); + cs_set(); } /* * Draw lines faster by calculating straight sections and drawing them with fastVline and fastHline. */ -#if defined (__STM32F1__) -void Adafruit_ILI9341_STM::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color) +void Adafruit_ILI9341_STM::drawLine(int16_t x0, int16_t y0, + int16_t x1, int16_t y1, uint16_t color) { if ((y0 < 0 && y1 <0) || (y0 > _height && y1 > _height)) return; if ((x0 < 0 && x1 <0) || (x0 > _width && x1 > _width)) return; @@ -600,8 +409,6 @@ void Adafruit_ILI9341_STM::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y } int16_t xbegin = x0; - lineBuffer[0] = color; - *csport &= ~cspinmask; if (steep) { for (; x0 <= x1; x0++) { err -= dy; @@ -649,11 +456,7 @@ void Adafruit_ILI9341_STM::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y drawFastHLine(xbegin, y0, x0 - xbegin, color); } } - *csport |= cspinmask; } -#endif - - // Pass 8-bit (each) R,G,B, get back 16-bit packed color uint16_t Adafruit_ILI9341_STM::color565(uint8_t r, uint8_t g, uint8_t b) { @@ -669,116 +472,133 @@ uint16_t Adafruit_ILI9341_STM::color565(uint8_t r, uint8_t g, uint8_t b) { #define MADCTL_BGR 0x08 #define MADCTL_MH 0x04 -void Adafruit_ILI9341_STM::setRotation(uint8_t m) { - - if (hwSPI) spi_begin(); - writecommand(ILI9341_MADCTL); +void Adafruit_ILI9341_STM::setRotation(uint8_t m) +{ rotation = m % 4; // can't be higher than 3 switch (rotation) { case 0: - writedata(MADCTL_MX | MADCTL_BGR); + m = (MADCTL_MX | MADCTL_BGR); _width = ILI9341_TFTWIDTH; _height = ILI9341_TFTHEIGHT; break; case 1: - writedata(MADCTL_MV | MADCTL_BGR); + m = (MADCTL_MV | MADCTL_BGR); _width = ILI9341_TFTHEIGHT; _height = ILI9341_TFTWIDTH; break; case 2: - writedata(MADCTL_MY | MADCTL_BGR); + m = (MADCTL_MY | MADCTL_BGR); _width = ILI9341_TFTWIDTH; _height = ILI9341_TFTHEIGHT; break; case 3: - writedata(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); + m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); _width = ILI9341_TFTHEIGHT; _height = ILI9341_TFTWIDTH; break; } - if (hwSPI) spi_end(); + mSPI.setDataSize(DATA_SIZE_8BIT); + writecommand(ILI9341_MADCTL); + writedata(m); + cs_set(); + mSPI.setDataSize(DATA_SIZE_16BIT); } -void Adafruit_ILI9341_STM::invertDisplay(boolean i) { - if (hwSPI) spi_begin(); +void Adafruit_ILI9341_STM::invertDisplay(boolean i) +{ writecommand(i ? ILI9341_INVON : ILI9341_INVOFF); - if (hwSPI) spi_end(); + cs_set(); } -////////// stuff not actively being used, but kept for posterity +uint16_t Adafruit_ILI9341_STM::readPixel(int16_t x, int16_t y) +{ + mSPI.beginTransaction(SPISettings(_safe_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); + writecommand(ILI9341_CASET); // Column addr set + spiwrite16(x); + spiwrite16(x); + writecommand(ILI9341_PASET); // Row addr set + spiwrite16(y); + spiwrite16(y); + writecommand(ILI9341_RAMRD); // read GRAM + (void)spiread(); //dummy read + uint8_t r = spiread(); + uint8_t g = spiread(); + uint8_t b = spiread(); + cs_set(); -uint8_t Adafruit_ILI9341_STM::spiread(void) { - uint8_t r = 0; + mSPI.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT)); - if (hwSPI) { -#if defined (__AVR__) - uint8_t backupSPCR = SPCR; - SPCR = mySPCR; - SPDR = 0x00; - while (!(SPSR & _BV(SPIF))); - r = SPDR; - SPCR = backupSPCR; -#elif defined(TEENSYDUINO) - r = SPI.transfer(0x00); -#elif defined (__STM32F1__) - r = SPI.transfer(0x00); -#elif defined (__arm__) - SPI.setClockDivider(11); // 8-ish MHz (full! speed!) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - r = SPI.transfer(0x00); -#endif - } else { + return color565(r, g, b); +} - for (uint8_t i = 0; i < 8; i++) { - digitalWrite(_sclk, LOW); - digitalWrite(_sclk, HIGH); - r <<= 1; - if (digitalRead(_miso)) - r |= 0x1; - } +uint16_t Adafruit_ILI9341_STM::readPixels(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t *buf) +{ + mSPI.beginTransaction(SPISettings(_safe_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); + + writecommand(ILI9341_CASET); // Column addr set + spiwrite16(x1); + spiwrite16(x2); + writecommand(ILI9341_PASET); // Row addr set + spiwrite16(y1); + spiwrite16(y2); + writecommand(ILI9341_RAMRD); // read GRAM + (void)spiread(); //dummy read + uint8_t r, g, b; + uint16_t len = (x2-x1+1)*(y2-y1+1); + uint16_t ret = len; + while (len--) { + r = spiread(); + g = spiread(); + b = spiread(); + *buf++ = color565(r, g, b); } - //Serial.print("read: 0x"); Serial.print(r, HEX); + cs_set(); - return r; + mSPI.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT)); + return ret; } -uint8_t Adafruit_ILI9341_STM::readdata(void) { - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); + +uint16_t Adafruit_ILI9341_STM::readPixelsRGB24(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t *buf) +{ + mSPI.beginTransaction(SPISettings(_safe_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); + + writecommand(ILI9341_CASET); // Column addr set + spiwrite16(x1); + spiwrite16(x2); + writecommand(ILI9341_PASET); // Row addr set + spiwrite16(y1); + spiwrite16(y2); + writecommand(ILI9341_RAMRD); // read GRAM + (void)spiread(); //dummy read + uint8_t r, g, b; + uint16_t len = (x2-x1+1)*(y2-y1+1); + uint16_t ret = len; + + mSPI.dmaTransfer(buf, buf, len*3); + cs_set(); + + mSPI.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT)); + return ret; +} + +uint8_t Adafruit_ILI9341_STM::readcommand8(uint8_t c, uint8_t index) +{ + // the SPI clock must be set lower + mSPI.beginTransaction(SPISettings(_safe_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); + + writecommand(c); uint8_t r = spiread(); - digitalWrite(_cs, HIGH); + cs_set(); + mSPI.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT)); return r; } -uint8_t Adafruit_ILI9341_STM::readcommand8(uint8_t c, uint8_t index) { - if (hwSPI) spi_begin(); - digitalWrite(_dc, LOW); // command - digitalWrite(_cs, LOW); - spiwrite(0xD9); // woo sekret command? - digitalWrite(_dc, HIGH); // data - spiwrite(0x10 + index); - digitalWrite(_cs, HIGH); - - digitalWrite(_dc, LOW); - //if(hwSPI) digitalWrite(_sclk, LOW); - digitalWrite(_cs, LOW); - spiwrite(c); - - digitalWrite(_dc, HIGH); - uint8_t r = spiread(); - digitalWrite(_cs, HIGH); - if (hwSPI) spi_end(); - return r; -} - - - /* uint16_t Adafruit_ILI9341_STM::readcommand16(uint8_t c) { diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h index a716c27..692015c 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h @@ -7,9 +7,12 @@ This library has been modified for the Maple Mini #define _ADAFRUIT_ILI9341H_ #include "Arduino.h" -#include "Print.h" #include -#include +#include + +#ifndef swap + #define swap(a, b) { int16_t t = a; a = b; b = t; } +#endif #define ILI9341_TFTWIDTH 240 #define ILI9341_TFTHEIGHT 320 @@ -92,21 +95,19 @@ This library has been modified for the Maple Mini #define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ #define ILI9341_PINK 0xF81F -class Adafruit_ILI9341_STM : public Adafruit_GFX { +class Adafruit_ILI9341_STM : public Adafruit_GFX_AS { public: - Adafruit_ILI9341_STM(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, - int8_t _RST, int8_t _MISO); Adafruit_ILI9341_STM(int8_t _CS, int8_t _DC, int8_t _RST = -1); - - void begin(void), - setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1), + + void begin(SPIClass & spi, uint32_t freq=48000000); + void begin(void) { begin(SPI); } + void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1), pushColor(uint16_t color), + pushColors(void * colorBuffer, uint16_t nr_pixels, uint8_t async=0), fillScreen(uint16_t color), - #if defined (__STM32F1__) drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color), - #endif drawPixel(int16_t x, int16_t y, uint16_t color), drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), @@ -117,43 +118,49 @@ class Adafruit_ILI9341_STM : public Adafruit_GFX { uint16_t color565(uint8_t r, uint8_t g, uint8_t b); /* These are not for current use, 8-bit protocol only! */ - uint8_t readdata(void), - readcommand8(uint8_t reg, uint8_t index = 0); + uint16_t readPixel(int16_t x, int16_t y); + uint16_t readPixels(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t *buf); + uint16_t readPixelsRGB24(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t *buf); + + uint8_t readcommand8(uint8_t reg, uint8_t index = 0); /* uint16_t readcommand16(uint8_t); uint32_t readcommand32(uint8_t); - void dummyclock(void); - */ + */ - void spiwrite(uint8_t), - writecommand(uint8_t c), - writedata(uint8_t d), - commandList(uint8_t *addr); - uint8_t spiread(void); +#define DMA_ON_LIMIT 250 // do DMA only for more data than this +#define SAFE_FREQ 24000000ul // 24MHz for reading +#define writePixel drawPixel + +#define dc_command() ( *dcport =(uint32_t)dcpinmask<<16 ) // 0 +#define dc_data() ( *dcport =(uint32_t)dcpinmask ) // 1 +#define cs_clear() ( *csport =(uint32_t)cspinmask<<16 ) +#define cs_set() ( *csport =(uint32_t)cspinmask ) +#define clk_clear() ( *clkport =(uint32_t)clkpinmask<<16 ) +#define clk_set() ( *clkport =(uint32_t)clkpinmask ) +#define mosi_clear() ( *mosiport=(uint32_t)misopinmask<<16 ) +#define mosi_set() ( *mosiport=(uint32_t)misopinmask ) +#define miso_in() ( (*misoport)&misopinmask ) + + inline uint8_t spiread(void) { return mSPI.transfer(0x00); } + inline uint8_t readdata(void) { return mSPI.transfer(0x00); } + inline void writedata(uint8_t c) { mSPI.write(c); } + inline void spiwrite(uint16_t c) { mSPI.write(c); } + inline void spiwrite16(uint16_t c) { mSPI.write16(c); } // 8 bit mode + + void writecommand(uint8_t c), + commandList(uint8_t *addr); private: - uint8_t tabcolor; + uint32_t _freq, _safe_freq; + SPIClass & mSPI = SPI; - - - - boolean hwSPI; -#if defined (__AVR__) || defined(TEENSYDUINO) - uint8_t mySPCR; - volatile uint8_t *mosiport, *clkport, *dcport, *rsport, *csport; - int8_t _cs, _dc, _rst, _mosi, _miso, _sclk; - uint8_t mosipinmask, clkpinmask, cspinmask, dcpinmask; -#elif defined (__STM32F1__) - volatile uint32 *mosiport, *clkport, *dcport, *rsport, *csport; - uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; - uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask; - uint16_t lineBuffer[ILI9341_TFTHEIGHT]; // DMA buffer. 16bit color data per pixel -#elif defined (__arm__) - volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport; - uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; - uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask; -#endif + volatile uint32_t *csport, *dcport; + int8_t _cs, _dc, _rst; + uint16_t cspinmask, dcpinmask; + uint16_t lineBuffer[ILI9341_TFTHEIGHT]; // DMA buffer. 16bit color data per pixel }; + #endif diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/graphicstest/graphicstest.ino b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/graphicstest/graphicstest.ino index c75c995..872b3e5 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/graphicstest/graphicstest.ino +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/graphicstest/graphicstest.ino @@ -15,7 +15,7 @@ #include "SPI.h" -#include "Adafruit_GFX.h" +#include "Adafruit_GFX_AS.h" #include "Adafruit_ILI9341_STM.h" // For the Adafruit shield, these are the default. @@ -346,4 +346,4 @@ unsigned long testFilledRoundRects() { } return micros() - start; -} \ No newline at end of file +} diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton/onoffbutton.ino b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton/onoffbutton.ino index b373835..5f60496 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton/onoffbutton.ino +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton/onoffbutton.ino @@ -3,7 +3,7 @@ // //Thanks to Adafruit forums member Asteroid for the original sketch! // -#include +#include #include #include #include diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton_breakout/onoffbutton_breakout.ino b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton_breakout/onoffbutton_breakout.ino index 9e35441..ad8fef2 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton_breakout/onoffbutton_breakout.ino +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/onoffbutton_breakout/onoffbutton_breakout.ino @@ -3,7 +3,7 @@ // //Thanks to Adafruit forums member Asteroid for the original sketch! // -#include +#include #include #include #include diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/spitftbitmap/spitftbitmap.ino b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/spitftbitmap/spitftbitmap.ino index 84ff464..5e46d68 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/spitftbitmap/spitftbitmap.ino +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/spitftbitmap/spitftbitmap.ino @@ -14,7 +14,7 @@ ****************************************************/ -#include // Core graphics library +#include // Core graphics library #include "Adafruit_ILI9341_STM.h" // Hardware-specific library #include #include diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/touchpaint/touchpaint.ino b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/touchpaint/touchpaint.ino index e10ecd9..0b29cd4 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/examples/touchpaint/touchpaint.ino +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/examples/touchpaint/touchpaint.ino @@ -14,10 +14,10 @@ ****************************************************/ -#include // Core graphics library +#include // Core graphics library #include #include // this is needed even tho we aren't using it -#include +#include #include // This is calibration data for the raw touch data to the screen coordinates diff --git a/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.cpp b/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.cpp index c0c24a0..34215da 100644 --- a/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.cpp +++ b/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.cpp @@ -22,13 +22,17 @@ All text above, and the splash screen below must be included in any redistributi //#endif #include -//#include -#include -//HardWire HWIRE(1,I2C_FAST_MODE); // I2c1 -HardWire HWIRE(2,I2C_FAST_MODE); // I2c2 + +#include +//TwoWire WIRE(1,I2C_FAST_MODE); // I2c1 +//TwoWire WIRE(2,I2C_FAST_MODE); // I2c2 #include "Adafruit_GFX.h" #include "Adafruit_SSD1306_STM32.h" +#ifndef swap +#define swap(a, b) { int16_t t = a; a = b; b = t; } +#endif + // the memory buffer for the LCD static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8] = { @@ -193,7 +197,7 @@ void Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) { else { // I2C Init - HWIRE.begin(); + Wire.begin(); #ifdef __SAM3X8E__ // Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL) @@ -355,10 +359,10 @@ void Adafruit_SSD1306::ssd1306_command(uint8_t c) { { // I2C uint8_t control = 0x00; // Co = 0, D/C = 0 - HWIRE.beginTransmission(_i2caddr); + Wire.beginTransmission(_i2caddr); WIRE_WRITE(control); WIRE_WRITE(c); - HWIRE.endTransmission(); + Wire.endTransmission(); } } @@ -469,10 +473,10 @@ void Adafruit_SSD1306::ssd1306_data(uint8_t c) { { // I2C uint8_t control = 0x40; // Co = 0, D/C = 1 - HWIRE.beginTransmission(_i2caddr); + Wire.beginTransmission(_i2caddr); WIRE_WRITE(control); WIRE_WRITE(c); - HWIRE.endTransmission(); + Wire.endTransmission(); } } @@ -521,14 +525,14 @@ void Adafruit_SSD1306::display(void) { // I2C for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) { // send a bunch of data in one xmission - HWIRE.beginTransmission(_i2caddr); + Wire.beginTransmission(_i2caddr); WIRE_WRITE(0x40); for (uint8_t x=0; x<16; x++) { WIRE_WRITE(buffer[i]); i++; } i--; - HWIRE.endTransmission(); + Wire.endTransmission(); } /* #ifndef __SAM3X8E__ diff --git a/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.h b/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.h index 0686d76..f91ff1b 100644 --- a/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.h +++ b/STM32F1/libraries/Adafruit_SSD1306/Adafruit_SSD1306_STM32.h @@ -18,10 +18,10 @@ All text above, and the splash screen must be included in any redistribution #if ARDUINO >= 100 #include "Arduino.h" - #define WIRE_WRITE HWIRE.write + #define WIRE_WRITE Wire.write #else #include "WProgram.h" - #define WIRE_WRITE HWIRE.send + #define WIRE_WRITE Wire.send #endif /* #ifdef __SAM3X8E__ diff --git a/STM32F1/libraries/Adafruit_SSD1306/STM32 README.txt b/STM32F1/libraries/Adafruit_SSD1306/STM32 README.txt index 54705cf..518aabe 100644 --- a/STM32F1/libraries/Adafruit_SSD1306/STM32 README.txt +++ b/STM32F1/libraries/Adafruit_SSD1306/STM32 README.txt @@ -1,6 +1,6 @@ STM32 adaption by Matthias Diro, 25.03.2015 Things to know: -This adaption uses hardware I2C (hardwire.h), Port: I2c2. SDA=0, SCL=1 on maple mini +This adaption uses hardware I2C (now Wire.h), Port: I2c2. SDA=0, SCL=1 on maple mini To change it to Port I2C1: -//HardWire HWIRE(1,I2C_FAST_MODE); // I2c1 -HardWire HWIRE(2,I2C_FAST_MODE); // I2c2 \ No newline at end of file +//TwoWire WIRE(1,I2C_FAST_MODE); // I2c1 +TwoWire WIRE(2,I2C_FAST_MODE); // I2c2 \ No newline at end of file diff --git a/STM32F1/libraries/Adafruit_SSD1306/examples/ssd1306_128x64_i2c_STM32/ssd1306_128x64_i2c_STM32.ino b/STM32F1/libraries/Adafruit_SSD1306/examples/ssd1306_128x64_i2c_STM32/ssd1306_128x64_i2c_STM32.ino index b11bdc0..5b68b3f 100644 --- a/STM32F1/libraries/Adafruit_SSD1306/examples/ssd1306_128x64_i2c_STM32/ssd1306_128x64_i2c_STM32.ino +++ b/STM32F1/libraries/Adafruit_SSD1306/examples/ssd1306_128x64_i2c_STM32/ssd1306_128x64_i2c_STM32.ino @@ -1,7 +1,7 @@ /* STM32 adaption by Matthias Diro, tested with maple mini and heltec OLED 12864 I2c; adress: 0x3C (SPI should work, but I didn't own one) Things to know: - This adaption uses hardware I2C (hardwire.h), Port: I2c2. SDA=0, SCL=1 on maple mini + This adaption uses hardware I2C (now Wire.h), Port: I2c2. SDA=0, SCL=1 on maple mini further details: STM32_README.txt */ /********************************************************************* diff --git a/STM32F1/libraries/EEPROM/EEPROM.cpp b/STM32F1/libraries/EEPROM/EEPROM.cpp index 289a93a..ed4d046 100644 --- a/STM32F1/libraries/EEPROM/EEPROM.cpp +++ b/STM32F1/libraries/EEPROM/EEPROM.cpp @@ -13,10 +13,10 @@ uint16 EEPROMClass::EE_CheckPage(uint32 pageBase, uint16 status) uint32 pageEnd = pageBase + (uint32)PageSize; // Page Status not EEPROM_ERASED and not a "state" - if ((*(__io uint16*)pageBase) != EEPROM_ERASED && (*(__io uint16*)pageBase) != status) + if ((*(__IO uint16*)pageBase) != EEPROM_ERASED && (*(__IO uint16*)pageBase) != status) return EEPROM_BAD_FLASH; for(pageBase += 4; pageBase < pageEnd; pageBase += 4) - if ((*(__io uint32*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty + if ((*(__IO uint32*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty return EEPROM_BAD_FLASH; return EEPROM_OK; } @@ -31,9 +31,9 @@ uint16 EEPROMClass::EE_CheckPage(uint32 pageBase, uint16 status) FLASH_Status EEPROMClass::EE_ErasePage(uint32 pageBase) { FLASH_Status FlashStatus; - uint16 data = (*(__io uint16*)(pageBase)); + uint16 data = (*(__IO uint16*)(pageBase)); if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA)) - data = (*(__io uint16*)(pageBase + 2)) + 1; + data = (*(__IO uint16*)(pageBase + 2)) + 1; else data = 0; @@ -73,8 +73,8 @@ uint16 EEPROMClass::EE_CheckErasePage(uint32 pageBase, uint16 status) */ uint32 EEPROMClass::EE_FindValidPage(void) { - uint16 status0 = (*(__io uint16*)PageBase0); // Get Page0 actual status - uint16 status1 = (*(__io uint16*)PageBase1); // Get Page1 actual status + uint16 status0 = (*(__IO uint16*)PageBase0); // Get Page0 actual status + uint16 status1 = (*(__IO uint16*)PageBase1); // Get Page1 actual status if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED) return PageBase0; @@ -100,14 +100,14 @@ uint16 EEPROMClass::EE_GetVariablesCount(uint32 pageBase, uint16 skipAddress) for (pageBase += 6; pageBase < pageEnd; pageBase += 4) { - varAddress = (*(__io uint16*)pageBase); + varAddress = (*(__IO uint16*)pageBase); if (varAddress == 0xFFFF || varAddress == skipAddress) continue; count++; for(idx = pageBase + 4; idx < pageEnd; idx += 4) { - nextAddress = (*(__io uint16*)idx); + nextAddress = (*(__IO uint16*)idx); if (nextAddress == varAddress) { count--; @@ -140,7 +140,7 @@ uint16 EEPROMClass::EE_PageTransfer(uint32 newPage, uint32 oldPage, uint16 SkipA // Find first free element in new page for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4) - if ((*(__io uint32*)newIdx) == 0xFFFFFFFF) // Verify if element + if ((*(__IO uint32*)newIdx) == 0xFFFFFFFF) // Verify if element break; // contents are 0xFFFFFFFF if (newIdx >= newEnd) return EEPROM_OUT_SIZE; @@ -150,13 +150,13 @@ uint16 EEPROMClass::EE_PageTransfer(uint32 newPage, uint32 oldPage, uint16 SkipA for (; oldIdx > oldEnd; oldIdx -= 4) { - address = *(__io uint16*)oldIdx; + address = *(__IO uint16*)oldIdx; if (address == 0xFFFF || address == SkipAddress) continue; // it's means that power off after write data found = 0; for (idx = newPage + 6; idx < newIdx; idx += 4) - if ((*(__io uint16*)(idx)) == address) + if ((*(__IO uint16*)(idx)) == address) { found = 1; break; @@ -167,7 +167,7 @@ uint16 EEPROMClass::EE_PageTransfer(uint32 newPage, uint32 oldPage, uint16 SkipA if (newIdx < newEnd) { - data = (*(__io uint16*)(oldIdx - 2)); + data = (*(__IO uint16*)(oldIdx - 2)); FlashStatus = FLASH_ProgramHalfWord(newIdx, data); if (FlashStatus != FLASH_COMPLETE) @@ -223,9 +223,9 @@ uint16 EEPROMClass::EE_VerifyPageFullWriteVariable(uint16 Address, uint16 Data) for (idx = pageEnd - 2; idx > pageBase; idx -= 4) { - if ((*(__io uint16*)idx) == Address) // Find last value for address + if ((*(__IO uint16*)idx) == Address) // Find last value for address { - count = (*(__io uint16*)(idx - 2)); // Read last data + count = (*(__IO uint16*)(idx - 2)); // Read last data if (count == Data) return EEPROM_OK; if (count == 0xFFFF) @@ -240,7 +240,7 @@ uint16 EEPROMClass::EE_VerifyPageFullWriteVariable(uint16 Address, uint16 Data) // Check each active page address starting from begining for (idx = pageBase + 4; idx < pageEnd; idx += 4) - if ((*(__io uint32*)idx) == 0xFFFFFFFF) // Verify if element + if ((*(__IO uint32*)idx) == 0xFFFFFFFF) // Verify if element { // contents are 0xFFFFFFFF FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data if (FlashStatus != FLASH_COMPLETE) @@ -303,8 +303,8 @@ uint16 EEPROMClass::init(void) FLASH_Unlock(); Status = EEPROM_NO_VALID_PAGE; - status0 = (*(__io uint16 *)PageBase0); - status1 = (*(__io uint16 *)PageBase1); + status0 = (*(__IO uint16 *)PageBase0); + status1 = (*(__IO uint16 *)PageBase1); switch (status0) { @@ -407,7 +407,7 @@ uint16 EEPROMClass::format(void) status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE); if (status != EEPROM_OK) return status; - if ((*(__io uint16*)PageBase0) == EEPROM_ERASED) + if ((*(__IO uint16*)PageBase0) == EEPROM_ERASED) { // Set Page0 as valid page: Write VALID_PAGE at Page0 base address FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); @@ -437,7 +437,7 @@ uint16 EEPROMClass::erases(uint16 *Erases) if (pageBase == 0) return EEPROM_NO_VALID_PAGE; - *Erases = (*(__io uint16*)pageBase+2); + *Erases = (*(__IO uint16*)pageBase+2); return EEPROM_OK; } @@ -485,9 +485,9 @@ uint16 EEPROMClass::read(uint16 Address, uint16 *Data) // Check each active page address starting from end for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4) - if ((*(__io uint16*)pageEnd) == Address) // Compare the read address with the virtual address + if ((*(__IO uint16*)pageEnd) == Address) // Compare the read address with the virtual address { - *Data = (*(__io uint16*)(pageEnd - 2)); // Get content of Address-2 which is variable value + *Data = (*(__IO uint16*)(pageEnd - 2)); // Get content of Address-2 which is variable value return EEPROM_OK; } diff --git a/STM32F1/libraries/EEPROM/flash_stm32.c b/STM32F1/libraries/EEPROM/flash_stm32.c index 364e64e..5c7a3fe 100644 --- a/STM32F1/libraries/EEPROM/flash_stm32.c +++ b/STM32F1/libraries/EEPROM/flash_stm32.c @@ -17,7 +17,7 @@ */ static void delay(void) { - __io uint32 i = 0; + __IO uint32 i = 0; for(i = 0xFF; i != 0; i--) { } } @@ -122,7 +122,7 @@ FLASH_Status FLASH_ProgramHalfWord(uint32 Address, uint16 Data) { /* if the previous operation is completed, proceed to program the new data */ FLASH_BASE->CR |= FLASH_CR_PG; - *(__io uint16*)Address = Data; + *(__IO uint16*)Address = Data; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status != FLASH_TIMEOUT) diff --git a/STM32F1/libraries/FreeRTOS/MapleFreeRTOS.cpp b/STM32F1/libraries/FreeRTOS701/MapleFreeRTOS.cpp similarity index 100% rename from STM32F1/libraries/FreeRTOS/MapleFreeRTOS.cpp rename to STM32F1/libraries/FreeRTOS701/MapleFreeRTOS.cpp diff --git a/STM32F1/libraries/FreeRTOS/MapleFreeRTOS.h b/STM32F1/libraries/FreeRTOS701/MapleFreeRTOS.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/MapleFreeRTOS.h rename to STM32F1/libraries/FreeRTOS701/MapleFreeRTOS.h diff --git a/STM32F1/libraries/FreeRTOS/keywords.txt b/STM32F1/libraries/FreeRTOS701/keywords.txt similarity index 100% rename from STM32F1/libraries/FreeRTOS/keywords.txt rename to STM32F1/libraries/FreeRTOS701/keywords.txt diff --git a/STM32F1/libraries/FreeRTOS/rules.mk b/STM32F1/libraries/FreeRTOS701/rules.mk similarity index 100% rename from STM32F1/libraries/FreeRTOS/rules.mk rename to STM32F1/libraries/FreeRTOS701/rules.mk diff --git a/STM32F1/libraries/FreeRTOS/utility/FreeRTOS.h b/STM32F1/libraries/FreeRTOS701/utility/FreeRTOS.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/FreeRTOS.h rename to STM32F1/libraries/FreeRTOS701/utility/FreeRTOS.h diff --git a/STM32F1/libraries/FreeRTOS/utility/FreeRTOSConfig.h b/STM32F1/libraries/FreeRTOS701/utility/FreeRTOSConfig.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/FreeRTOSConfig.h rename to STM32F1/libraries/FreeRTOS701/utility/FreeRTOSConfig.h diff --git a/STM32F1/libraries/FreeRTOS/utility/StackMacros.h b/STM32F1/libraries/FreeRTOS701/utility/StackMacros.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/StackMacros.h rename to STM32F1/libraries/FreeRTOS701/utility/StackMacros.h diff --git a/STM32F1/libraries/FreeRTOS/utility/croutine.c b/STM32F1/libraries/FreeRTOS701/utility/croutine.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/croutine.c rename to STM32F1/libraries/FreeRTOS701/utility/croutine.c diff --git a/STM32F1/libraries/FreeRTOS/utility/croutine.h b/STM32F1/libraries/FreeRTOS701/utility/croutine.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/croutine.h rename to STM32F1/libraries/FreeRTOS701/utility/croutine.h diff --git a/STM32F1/libraries/FreeRTOS/utility/heap_2.c b/STM32F1/libraries/FreeRTOS701/utility/heap_2.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/heap_2.c rename to STM32F1/libraries/FreeRTOS701/utility/heap_2.c diff --git a/STM32F1/libraries/FreeRTOS/utility/list.c b/STM32F1/libraries/FreeRTOS701/utility/list.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/list.c rename to STM32F1/libraries/FreeRTOS701/utility/list.c diff --git a/STM32F1/libraries/FreeRTOS/utility/list.h b/STM32F1/libraries/FreeRTOS701/utility/list.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/list.h rename to STM32F1/libraries/FreeRTOS701/utility/list.h diff --git a/STM32F1/libraries/FreeRTOS/utility/mpu_wrappers.h b/STM32F1/libraries/FreeRTOS701/utility/mpu_wrappers.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/mpu_wrappers.h rename to STM32F1/libraries/FreeRTOS701/utility/mpu_wrappers.h diff --git a/STM32F1/libraries/FreeRTOS/utility/port.c b/STM32F1/libraries/FreeRTOS701/utility/port.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/port.c rename to STM32F1/libraries/FreeRTOS701/utility/port.c diff --git a/STM32F1/libraries/FreeRTOS/utility/portable.h b/STM32F1/libraries/FreeRTOS701/utility/portable.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/portable.h rename to STM32F1/libraries/FreeRTOS701/utility/portable.h diff --git a/STM32F1/libraries/FreeRTOS/utility/portmacro.h b/STM32F1/libraries/FreeRTOS701/utility/portmacro.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/portmacro.h rename to STM32F1/libraries/FreeRTOS701/utility/portmacro.h diff --git a/STM32F1/libraries/FreeRTOS/utility/projdefs.h b/STM32F1/libraries/FreeRTOS701/utility/projdefs.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/projdefs.h rename to STM32F1/libraries/FreeRTOS701/utility/projdefs.h diff --git a/STM32F1/libraries/FreeRTOS/utility/queue.c b/STM32F1/libraries/FreeRTOS701/utility/queue.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/queue.c rename to STM32F1/libraries/FreeRTOS701/utility/queue.c diff --git a/STM32F1/libraries/FreeRTOS/utility/queue.h b/STM32F1/libraries/FreeRTOS701/utility/queue.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/queue.h rename to STM32F1/libraries/FreeRTOS701/utility/queue.h diff --git a/STM32F1/libraries/FreeRTOS/utility/semphr.h b/STM32F1/libraries/FreeRTOS701/utility/semphr.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/semphr.h rename to STM32F1/libraries/FreeRTOS701/utility/semphr.h diff --git a/STM32F1/libraries/FreeRTOS/utility/task.h b/STM32F1/libraries/FreeRTOS701/utility/task.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/task.h rename to STM32F1/libraries/FreeRTOS701/utility/task.h diff --git a/STM32F1/libraries/FreeRTOS/utility/tasks.c b/STM32F1/libraries/FreeRTOS701/utility/tasks.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/tasks.c rename to STM32F1/libraries/FreeRTOS701/utility/tasks.c diff --git a/STM32F1/libraries/FreeRTOS/utility/timers.c b/STM32F1/libraries/FreeRTOS701/utility/timers.c similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/timers.c rename to STM32F1/libraries/FreeRTOS701/utility/timers.c diff --git a/STM32F1/libraries/FreeRTOS/utility/timers.h b/STM32F1/libraries/FreeRTOS701/utility/timers.h similarity index 100% rename from STM32F1/libraries/FreeRTOS/utility/timers.h rename to STM32F1/libraries/FreeRTOS701/utility/timers.h diff --git a/STM32F3/cores/maple/libmaple/pwr.c b/STM32F1/libraries/FreeRTOS900/MapleFreeRTOS900.cpp similarity index 76% rename from STM32F3/cores/maple/libmaple/pwr.c rename to STM32F1/libraries/FreeRTOS900/MapleFreeRTOS900.cpp index 3cf170f..43fc2f1 100644 --- a/STM32F3/cores/maple/libmaple/pwr.c +++ b/STM32F1/libraries/FreeRTOS900/MapleFreeRTOS900.cpp @@ -24,18 +24,21 @@ * SOFTWARE. *****************************************************************************/ -/** - * @file libmaple/pwr.c - * @brief Power control (PWR) support. - */ +#include "MapleFreeRTOS900.h" -#include -#include +extern "C" { + +void vApplicationStackOverflowHook(xTaskHandle *pxTask, + signed char *pcTaskName) { + /* This function will get called if a task overflows its stack. + * If the parameters are corrupt then inspect pxCurrentTCB to find + * which was the offending task. */ + + (void) pxTask; + (void) pcTaskName; + + while (1) + ; +} -/** - * Enables the power interface clock, and resets the power device. - */ -void pwr_init(void) { - rcc_clk_enable(RCC_PWR); - rcc_reset_dev(RCC_PWR); } diff --git a/STM32F3/cores/maple/wirish/bits.h b/STM32F1/libraries/FreeRTOS900/MapleFreeRTOS900.h similarity index 83% rename from STM32F3/cores/maple/wirish/bits.h rename to STM32F1/libraries/FreeRTOS900/MapleFreeRTOS900.h index 0a63c58..4cbbb96 100644 --- a/STM32F3/cores/maple/wirish/bits.h +++ b/STM32F1/libraries/FreeRTOS900/MapleFreeRTOS900.h @@ -1,7 +1,7 @@ /****************************************************************************** * The MIT License * - * Copyright (c) 2010 LeafLabs, LLC. + * Copyright (c) 2011 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -24,12 +24,17 @@ * SOFTWARE. *****************************************************************************/ -/* Note: Use of this header file is deprecated. Use bit_constants.h - instead. */ +#ifndef __MAPLE_FREERTOS_H__ +#define __MAPLE_FREERTOS_H__ -#ifndef _WIRISH_BITS_H_ -#define _WIRISH_BITS_H_ +#include -#include +extern "C" { +#define GCC_ARMCM3 +#include "utility/FreeRTOS.h" +#include "utility/task.h" +#include "utility/queue.h" +#include "utility/semphr.h" +} #endif diff --git a/STM32F1/libraries/FreeRTOS900/examples/rtos_blink/rtos_blink.ino b/STM32F1/libraries/FreeRTOS900/examples/rtos_blink/rtos_blink.ino new file mode 100644 index 0000000..935c629 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/examples/rtos_blink/rtos_blink.ino @@ -0,0 +1,31 @@ +//#include +//#include "libraries/FreeRTOS/MapleFreeRTOS.h" +#include + +static void vLEDFlashTask(void *pvParameters) { + for (;;) { + vTaskDelay(1000); + digitalWrite(BOARD_LED_PIN, HIGH); + vTaskDelay(50); + digitalWrite(BOARD_LED_PIN, LOW); + } +} + +void setup() { + // initialize the digital pin as an output: + pinMode(BOARD_LED_PIN, OUTPUT); + + xTaskCreate(vLEDFlashTask, + "Task1", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + NULL); + vTaskStartScheduler(); +} + +void loop() { + // Insert background code here +} + + diff --git a/STM32F1/libraries/FreeRTOS900/examples/rtos_display_blink/rtos_display_blink.ino b/STM32F1/libraries/FreeRTOS900/examples/rtos_display_blink/rtos_display_blink.ino new file mode 100644 index 0000000..7d92100 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/examples/rtos_display_blink/rtos_display_blink.ino @@ -0,0 +1,212 @@ +#define USE_SEMAPHORE_DMA1 +#include +#include +#include +#include + +#define __CS 8 +#define __RST 9 +#define __DC 10 + +TFT_ILI9163C tft = TFT_ILI9163C(__CS, __DC, __RST); + +xSemaphoreHandle xDisplayFree; + + +const float sin_d[] = { + 0, 0.17, 0.34, 0.5, 0.64, 0.77, 0.87, 0.94, 0.98, 1, 0.98, 0.94, + 0.87, 0.77, 0.64, 0.5, 0.34, 0.17, 0, -0.17, -0.34, -0.5, -0.64, + -0.77, -0.87, -0.94, -0.98, -1, -0.98, -0.94, -0.87, -0.77, + -0.64, -0.5, -0.34, -0.17 +}; +const float cos_d[] = { + 1, 0.98, 0.94, 0.87, 0.77, 0.64, 0.5, 0.34, 0.17, 0, -0.17, -0.34, + -0.5, -0.64, -0.77, -0.87, -0.94, -0.98, -1, -0.98, -0.94, -0.87, + -0.77, -0.64, -0.5, -0.34, -0.17, 0, 0.17, 0.34, 0.5, 0.64, 0.77, + 0.87, 0.94, 0.98 +}; +const float d = 5; +float cube1_px[] = { + -d, d, d, -d, -d, d, d, -d +}; +float cube1_py[] = { + -d, -d, d, d, -d, -d, d, d +}; +float cube1_pz[] = { + -d, -d, -d, -d, d, d, d, d +}; + +float cube1_p2x[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; +float cube1_p2y[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +int cube1_r[] = { + 0, 0, 0 +}; +const float d2 = 10; +float cube2_px[] = { + -d2, d2, d2, -d2, -d2, d2, d2, -d2 +}; +float cube2_py[] = { + -d2, -d2, d2, d2, -d2, -d2, d2, d2 +}; +float cube2_pz[] = { + -d2, -d2, -d2, -d2, d2, d2, d2, d2 +}; + +float cube2_p2x[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; +float cube2_p2y[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +int cube2_r[] = { + 0, 0, 0 +}; + +uint16 cube1_x, cube1_y, cube2_x, cube2_y, cube1_color, cube2_color; + +static void vLEDFlashTask(void *pvParameters) { + for (;;) { + vTaskDelay(1000); + digitalWrite(BOARD_LED_PIN, HIGH); + vTaskDelay(50); + digitalWrite(BOARD_LED_PIN, LOW); + } +} + +static void vCube1LoopTask(void *pvParameters) { + while (1) { + if ( xSemaphoreTake( xDisplayFree, ( portTickType ) 10 ) == pdTRUE ) + { + cube(cube1_px, cube1_py, cube1_pz, cube1_p2x, cube1_p2y, cube1_r, &cube1_x, &cube1_y, &cube1_color); + xSemaphoreGive( xDisplayFree ); + vTaskDelay(15); + } + } +} + +static void vCube2LoopTask(void *pvParameters) { + while (1) { + if ( xSemaphoreTake( xDisplayFree, ( portTickType ) 10 ) == pdTRUE ) + { + cube(cube2_px, cube2_py, cube2_pz, cube2_p2x, cube2_p2y, cube2_r, &cube2_x, &cube2_y, &cube2_color); + xSemaphoreGive( xDisplayFree ); + vTaskDelay(40); + } + } +} + + +void cube(float *px, float *py, float *pz, float *p2x, float *p2y, int *r, uint16 *x, uint16 *y, uint16 *color) { + + for (int i = 0; i < 3; i++) { + tft.drawLine(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1], WHITE); + tft.drawLine(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5], WHITE); + tft.drawLine(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4], WHITE); + } + tft.drawLine(p2x[3], p2y[3], p2x[0], p2y[0], WHITE); + tft.drawLine(p2x[7], p2y[7], p2x[4], p2y[4], WHITE); + tft.drawLine(p2x[3], p2y[3], p2x[7], p2y[7], WHITE); + + r[0] = r[0] + 1; + r[1] = r[1] + 1; + if (r[0] == 36) r[0] = 0; + if (r[1] == 36) r[1] = 0; + if (r[2] == 36) r[2] = 0; + for (int i = 0; i < 8; i++) + { + float px2 = px[i]; + float py2 = cos_d[r[0]] * py[i] - sin_d[r[0]] * pz[i]; + float pz2 = sin_d[r[0]] * py[i] + cos_d[r[0]] * pz[i]; + + float px3 = cos_d[r[1]] * px2 + sin_d[r[1]] * pz2; + float py3 = py2; + float pz3 = -sin_d[r[1]] * px2 + cos_d[r[1]] * pz2; + + float ax = cos_d[r[2]] * px3 - sin_d[r[2]] * py3; + float ay = sin_d[r[2]] * px3 + cos_d[r[2]] * py3; + float az = pz3 - 190; + + p2x[i] = *x + ax * 500 / az; + p2y[i] = *y + ay * 500 / az; + } + + for (int i = 0; i < 3; i++) { + tft.drawLine(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1], *color); + tft.drawLine(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5], *color); + tft.drawLine(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4], *color); + } + tft.drawLine(p2x[3], p2y[3], p2x[0], p2y[0], *color); + tft.drawLine(p2x[7], p2y[7], p2x[4], p2y[4], *color); + tft.drawLine(p2x[3], p2y[3], p2x[7], p2y[7], *color); +} + +static void vSqrtTask(void *pvParameters) { + while (1){ + Serial.println ("Starting Sqrt calculations..."); + uint16 x = 0; + uint16 ixx[1001]; + // Library Sqrt + uint32_t t0 = millis(); + for (uint32_t n = 247583650 ; n > 247400000 ; n--) { + x = sqrt (n); + } + uint32_t t1 = millis() - t0; + Serial.print ("Sqrt calculations took (ms): "); + Serial.println (t1); + delay (5000); + } +} + +void setup() { + // initialize the digital pin as an output: + Serial.begin(9600); + delay (5000); + Serial.println ("Running..."); + pinMode(BOARD_LED_PIN, OUTPUT); + tft.begin(); + tft.fillScreen(WHITE); + cube1_x = ((tft.width()) / 4); + cube1_y = ((tft.height()) / 4); + cube2_x = ((tft.width()) / 2); + cube2_y = ((tft.height()) / 2); + cube1_color = BLACK; + cube2_color = RED; + vSemaphoreCreateBinary(xDisplayFree); + xTaskCreate(vLEDFlashTask, + "Task1", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + NULL); + xTaskCreate(vCube1LoopTask, + "Cube1", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + NULL); + xTaskCreate(vCube2LoopTask, + "Cube2", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY+1, + NULL); + xTaskCreate(vSqrtTask, + "Sqrt", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY, + NULL); + vTaskStartScheduler(); +} + +void loop() { + // Do not write any code here, it would not execute. +} + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/FreeRTOS.h b/STM32F1/libraries/FreeRTOS900/utility/FreeRTOS.h new file mode 100644 index 0000000..6838f47 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/FreeRTOS.h @@ -0,0 +1,1066 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* + * If stdint.h cannot be located then: + * + If using GCC ensure the -nostdint options is *not* being used. + * + Ensure the project's include path includes the directory in which your + * compiler stores stdint.h. + * + Set any compiler options necessary for it to support C99, as technically + * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any + * other way). + * + The FreeRTOS download includes a simple stdint.h definition that can be + * used in cases where none is provided by the compiler. The files only + * contains the typedefs required to build FreeRTOS. Read the instructions + * in FreeRTOS/source/stdint.readme for more information. + */ +#include /* READ COMMENT ABOVE. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + +/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ +#ifndef configUSE_NEWLIB_REENTRANT + #define configUSE_NEWLIB_REENTRANT 0 +#endif + +/* Required if struct _reent is used. */ +#if ( configUSE_NEWLIB_REENTRANT == 1 ) + #include +#endif +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configMINIMAL_STACK_SIZE + #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. +#endif + +#ifndef configMAX_PRIORITIES + #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS + #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configMAX_PRIORITIES + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + +#ifndef configUSE_CO_ROUTINES + #define configUSE_CO_ROUTINES 0 +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #define INCLUDE_vTaskPrioritySet 0 +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #define INCLUDE_uxTaskPriorityGet 0 +#endif + +#ifndef INCLUDE_vTaskDelete + #define INCLUDE_vTaskDelete 0 +#endif + +#ifndef INCLUDE_vTaskSuspend + #define INCLUDE_vTaskSuspend 0 +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #define INCLUDE_vTaskDelayUntil 0 +#endif + +#ifndef INCLUDE_vTaskDelay + #define INCLUDE_vTaskDelay 0 +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle + #define INCLUDE_xTaskGetIdleTaskHandle 0 +#endif + +#ifndef INCLUDE_xTaskAbortDelay + #define INCLUDE_xTaskAbortDelay 0 +#endif + +#ifndef INCLUDE_xQueueGetMutexHolder + #define INCLUDE_xQueueGetMutexHolder 0 +#endif + +#ifndef INCLUDE_xSemaphoreGetMutexHolder + #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder +#endif + +#ifndef INCLUDE_xTaskGetHandle + #define INCLUDE_xTaskGetHandle 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef INCLUDE_eTaskGetState + #define INCLUDE_eTaskGetState 0 +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xTimerPendFunctionCall + #define INCLUDE_xTimerPendFunctionCall 0 +#endif + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + +#if configUSE_CO_ROUTINES != 0 + #ifndef configMAX_CO_ROUTINE_PRIORITIES + #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. + #endif +#endif + +#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK + #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS + #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS + #define configUSE_TIMERS 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef configASSERT + #define configASSERT( x ) + #define configASSERT_DEFINED 0 +#else + #define configASSERT_DEFINED 1 +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + + #ifndef configTIMER_TASK_PRIORITY + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ + + #ifndef configTIMER_QUEUE_LENGTH + #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #endif /* configTIMER_QUEUE_LENGTH */ + + #ifndef configTIMER_TASK_STACK_DEPTH + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ + +#endif /* configUSE_TIMERS */ + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#endif + +#ifndef portCLEAN_UP_TCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef portPRE_TASK_DELETE_HOOK + #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) +#endif + +#ifndef portSETUP_TCB + #define portSETUP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) + #define pcQueueGetName( xQueue ) +#endif + +#ifndef portPOINTER_SIZE_TYPE + #define portPOINTER_SIZE_TYPE uint32_t +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART + /* Used to perform any necessary initialisation - for example, open a file + into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + /* Use to close a trace, for example close a file into which trace has been + written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + /* Called after a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceINCREASE_TICK_COUNT + /* Called before stepping the tick count after waking from tickless idle + sleep. */ + #define traceINCREASE_TICK_COUNT( x ) +#endif + +#ifndef traceLOW_POWER_IDLE_BEGIN + /* Called immediately before entering tickless idle. */ + #define traceLOW_POWER_IDLE_BEGIN() +#endif + +#ifndef traceLOW_POWER_IDLE_END + /* Called when returning to the Idle task after a tickless idle. */ + #define traceLOW_POWER_IDLE_END() +#endif + +#ifndef traceTASK_SWITCHED_OUT + /* Called before a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceTASK_PRIORITY_INHERIT + /* Called when a task attempts to take a mutex that is already held by a + lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task + that holds the mutex. uxInheritedPriority is the priority the mutex holder + will inherit (the priority of the task that is attempting to obtain the + muted. */ + #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) +#endif + +#ifndef traceTASK_PRIORITY_DISINHERIT + /* Called when a task releases a mutex, the holding of which had resulted in + the task inheriting the priority of a higher priority task. + pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the + mutex. uxOriginalPriority is the task's configured (base) priority. */ + #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + /* Task is about to block because it cannot read from a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the read was attempted. pxCurrentTCB points to the TCB of the + task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + /* Task is about to block because it cannot write to a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the write was attempted. pxCurrentTCB points to the TCB of the + task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceMOVED_TASK_TO_READY_STATE + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef tracePOST_MOVED_TASK_TO_READY_STATE + #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED( ucQueueType ) +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL( x ) +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE + #define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED + #define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED + #define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef traceMALLOC + #define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE + #define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef traceEVENT_GROUP_CREATE + #define traceEVENT_GROUP_CREATE( xEventGroup ) +#endif + +#ifndef traceEVENT_GROUP_CREATE_FAILED + #define traceEVENT_GROUP_CREATE_FAILED() +#endif + +#ifndef traceEVENT_GROUP_SYNC_BLOCK + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_SYNC_END + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_END + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS + #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR + #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS + #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_DELETE + #define traceEVENT_GROUP_DELETE( xEventGroup ) +#endif + +#ifndef tracePEND_FUNC_CALL + #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR + #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD + #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) +#endif + +#ifndef traceTASK_NOTIFY_TAKE_BLOCK + #define traceTASK_NOTIFY_TAKE_BLOCK() +#endif + +#ifndef traceTASK_NOTIFY_TAKE + #define traceTASK_NOTIFY_TAKE() +#endif + +#ifndef traceTASK_NOTIFY_WAIT_BLOCK + #define traceTASK_NOTIFY_WAIT_BLOCK() +#endif + +#ifndef traceTASK_NOTIFY_WAIT + #define traceTASK_NOTIFY_WAIT() +#endif + +#ifndef traceTASK_NOTIFY + #define traceTASK_NOTIFY() +#endif + +#ifndef traceTASK_NOTIFY_FROM_ISR + #define traceTASK_NOTIFY_FROM_ISR() +#endif + +#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR + #define traceTASK_NOTIFY_GIVE_FROM_ISR() +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT + #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef portSUPPRESS_TICKS_AND_SLEEP + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) +#endif + +#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP + #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 +#endif + +#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 + #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 +#endif + +#ifndef configUSE_TICKLESS_IDLE + #define configUSE_TICKLESS_IDLE 0 +#endif + +#ifndef configPRE_SLEEP_PROCESSING + #define configPRE_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPOST_SLEEP_PROCESSING + #define configPOST_SLEEP_PROCESSING( x ) +#endif + +#ifndef configUSE_QUEUE_SETS + #define configUSE_QUEUE_SETS 0 +#endif + +#ifndef portTASK_USES_FLOATING_POINT + #define portTASK_USES_FLOATING_POINT() +#endif + +#ifndef configUSE_TIME_SLICING + #define configUSE_TIME_SLICING 1 +#endif + +#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS + #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 +#endif + +#ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#endif + +#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() +#endif + +#ifndef configUSE_TRACE_FACILITY + #define configUSE_TRACE_FACILITY 0 +#endif + +#ifndef mtCOVERAGE_TEST_MARKER + #define mtCOVERAGE_TEST_MARKER() +#endif + +#ifndef mtCOVERAGE_TEST_DELAY + #define mtCOVERAGE_TEST_DELAY() +#endif + +#ifndef portASSERT_IF_IN_ISR + #define portASSERT_IF_IN_ISR() +#endif + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +#ifndef configAPPLICATION_ALLOCATED_HEAP + #define configAPPLICATION_ALLOCATED_HEAP 0 +#endif + +#ifndef configUSE_TASK_NOTIFICATIONS + #define configUSE_TASK_NOTIFICATIONS 1 +#endif + +#ifndef portTICK_TYPE_IS_ATOMIC + #define portTICK_TYPE_IS_ATOMIC 0 +#endif + +#ifndef configSUPPORT_STATIC_ALLOCATION + /* Defaults to 0 for backward compatibility. */ + #define configSUPPORT_STATIC_ALLOCATION 0 +#endif + +#ifndef configSUPPORT_DYNAMIC_ALLOCATION + /* Defaults to 1 for backward compatibility. */ + #define configSUPPORT_DYNAMIC_ALLOCATION 1 +#endif + +/* Sanity check the configuration. */ +#if( configUSE_TICKLESS_IDLE != 0 ) + #if( INCLUDE_vTaskSuspend != 1 ) + #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 + #endif /* INCLUDE_vTaskSuspend */ +#endif /* configUSE_TICKLESS_IDLE */ + +#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) + #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. +#endif + +#if( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) + #error configUSE_MUTEXES must be set to 1 to use recursive mutexes +#endif + +#if( portTICK_TYPE_IS_ATOMIC == 0 ) + /* Either variables of tick type cannot be read atomically, or + portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when + the tick count is returned to the standard critical section macros. */ + #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) +#else + /* The tick type can be read atomically, so critical sections used when the + tick count is returned can be defined away. */ + #define portTICK_TYPE_ENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x +#endif + +/* Definitions to allow backward compatibility with FreeRTOS versions prior to +V8 if desired. */ +#ifndef configENABLE_BACKWARD_COMPATIBILITY + #define configENABLE_BACKWARD_COMPATIBILITY 1 +#endif + +#if configENABLE_BACKWARD_COMPATIBILITY == 1 + #define eTaskStateGet eTaskGetState + #define portTickType TickType_t + #define xTaskHandle TaskHandle_t + #define xQueueHandle QueueHandle_t + #define xSemaphoreHandle SemaphoreHandle_t + #define xQueueSetHandle QueueSetHandle_t + #define xQueueSetMemberHandle QueueSetMemberHandle_t + #define xTimeOutType TimeOut_t + #define xMemoryRegion MemoryRegion_t + #define xTaskParameters TaskParameters_t + #define xTaskStatusType TaskStatus_t + #define xTimerHandle TimerHandle_t + #define xCoRoutineHandle CoRoutineHandle_t + #define pdTASK_HOOK_CODE TaskHookFunction_t + #define portTICK_RATE_MS portTICK_PERIOD_MS + #define pcTaskGetTaskName pcTaskGetName + #define pcTimerGetTimerName pcTimerGetName + #define pcQueueGetQueueName pcQueueGetName + #define vTaskGetTaskInfo vTaskGetInfo + + /* Backward compatibility within the scheduler code only - these definitions + are not really required but are included for completeness. */ + #define tmrTIMER_CALLBACK TimerCallbackFunction_t + #define pdTASK_CODE TaskFunction_t + #define xListItem ListItem_t + #define xList List_t +#endif /* configENABLE_BACKWARD_COMPATIBILITY */ + +#if( configUSE_ALTERNATIVE_API != 0 ) + #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 +#endif + +/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even +if floating point hardware is otherwise supported by the FreeRTOS port in use. +This constant is not supported by all FreeRTOS ports that include floating +point support. */ +#ifndef configUSE_TASK_FPU_SUPPORT + #define configUSE_TASK_FPU_SUPPORT 1 +#endif + +/* + * In line with software engineering best practice, FreeRTOS implements a strict + * data hiding policy, so the real structures used by FreeRTOS to maintain the + * state of tasks, queues, semaphores, etc. are not accessible to the application + * code. However, if the application writer wants to statically allocate such + * an object then the size of the object needs to be know. Dummy structures + * that are guaranteed to have the same size and alignment requirements of the + * real objects are used for this purpose. The dummy list and list item + * structures below are used for inclusion in such a dummy structure. + */ +struct xSTATIC_LIST_ITEM +{ + TickType_t xDummy1; + void *pvDummy2[ 4 ]; +}; +typedef struct xSTATIC_LIST_ITEM StaticListItem_t; + +/* See the comments above the struct xSTATIC_LIST_ITEM definition. */ +struct xSTATIC_MINI_LIST_ITEM +{ + TickType_t xDummy1; + void *pvDummy2[ 2 ]; +}; +typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; + +/* See the comments above the struct xSTATIC_LIST_ITEM definition. */ +typedef struct xSTATIC_LIST +{ + UBaseType_t uxDummy1; + void *pvDummy2; + StaticMiniListItem_t xDummy3; +} StaticList_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the Task structure used internally by + * FreeRTOS is not accessible to application code. However, if the application + * writer wants to statically allocate the memory required to create a task then + * the size of the task object needs to be know. The StaticTask_t structure + * below is provided for this purpose. Its sizes and alignment requirements are + * guaranteed to match those of the genuine structure, no matter which + * architecture is being used, and no matter how the values in FreeRTOSConfig.h + * are set. Its contents are somewhat obfuscated in the hope users will + * recognise that it would be unwise to make direct use of the structure members. + */ +typedef struct xSTATIC_TCB +{ + void *pxDummy1; + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xDummy2; + #endif + StaticListItem_t xDummy3[ 2 ]; + UBaseType_t uxDummy5; + void *pxDummy6; + uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; + #if ( portSTACK_GROWTH > 0 ) + void *pxDummy8; + #endif + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxDummy9; + #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy10[ 2 ]; + #endif + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxDummy12[ 2 ]; + #endif + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + void *pxDummy14; + #endif + #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulDummy16; + #endif + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + struct _reent xDummy17; + #endif + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + uint32_t ulDummy18; + uint8_t ucDummy19; + #endif + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t uxDummy20; + #endif + #if( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDummy21; + #endif + +} StaticTask_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the Queue structure used internally by + * FreeRTOS is not accessible to application code. However, if the application + * writer wants to statically allocate the memory required to create a queue + * then the size of the queue object needs to be know. The StaticQueue_t + * structure below is provided for this purpose. Its sizes and alignment + * requirements are guaranteed to match those of the genuine structure, no + * matter which architecture is being used, and no matter how the values in + * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope + * users will recognise that it would be unwise to make direct use of the + * structure members. + */ +typedef struct xSTATIC_QUEUE +{ + void *pvDummy1[ 3 ]; + + union + { + void *pvDummy2; + UBaseType_t uxDummy2; + } u; + + StaticList_t xDummy3[ 2 ]; + UBaseType_t uxDummy4[ 3 ]; + uint8_t ucDummy5[ 2 ]; + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy6; + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + void *pvDummy7; + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy8; + uint8_t ucDummy9; + #endif + +} StaticQueue_t; +typedef StaticQueue_t StaticSemaphore_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the event group structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create an event group then the size of the event group object needs to be + * know. The StaticEventGroup_t structure below is provided for this purpose. + * Its sizes and alignment requirements are guaranteed to match those of the + * genuine structure, no matter which architecture is being used, and no matter + * how the values in FreeRTOSConfig.h are set. Its contents are somewhat + * obfuscated in the hope users will recognise that it would be unwise to make + * direct use of the structure members. + */ +typedef struct xSTATIC_EVENT_GROUP +{ + TickType_t xDummy1; + StaticList_t xDummy2; + + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy3; + #endif + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy4; + #endif + +} StaticEventGroup_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the software timer structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create a software timer then the size of the queue object needs to be know. + * The StaticTimer_t structure below is provided for this purpose. Its sizes + * and alignment requirements are guaranteed to match those of the genuine + * structure, no matter which architecture is being used, and no matter how the + * values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in + * the hope users will recognise that it would be unwise to make direct use of + * the structure members. + */ +typedef struct xSTATIC_TIMER +{ + void *pvDummy1; + StaticListItem_t xDummy2; + TickType_t xDummy3; + UBaseType_t uxDummy4; + void *pvDummy5[ 2 ]; + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy6; + #endif + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy7; + #endif + +} StaticTimer_t; + +#ifdef __cplusplus +} +#endif + +#endif /* INC_FREERTOS_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/FreeRTOSConfig.h b/STM32F1/libraries/FreeRTOS900/utility/FreeRTOSConfig.h new file mode 100644 index 0000000..87d6c5d --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/FreeRTOSConfig.h @@ -0,0 +1,144 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( ( unsigned long ) F_CPU ) +#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +#define configUSE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 0 +#define configGENERATE_RUN_TIME_STATS 0 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 + +/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255 +(lowest) to 0 (1?) (highest). */ +#define configKERNEL_INTERRUPT_PRIORITY 255 +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */ + + +/* This is the value being used as per the ST library which permits 16 +priority values, 0 to 15. This must correspond to the +configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest +NVIC value of 255. */ +#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15 + +/*----------------------------------------------------------- + * UART configuration. + *-----------------------------------------------------------*/ +#define configCOM0_RX_BUFFER_LENGTH 128 +#define configCOM0_TX_BUFFER_LENGTH 128 +#define configCOM1_RX_BUFFER_LENGTH 128 +#define configCOM1_TX_BUFFER_LENGTH 128 + +#endif /* FREERTOS_CONFIG_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_1.c b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_1.c new file mode 100644 index 0000000..178ff7c --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_1.c @@ -0,0 +1,174 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * The simplest possible implementation of pvPortMalloc(). Note that this + * implementation does NOT allow allocated memory to be freed again. + * + * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +static size_t xNextFreeByte = ( size_t ) 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn = NULL; +static uint8_t *pucAlignedHeap = NULL; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + #if portBYTE_ALIGNMENT != 1 + if( xWantedSize & portBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + #endif + + vTaskSuspendAll(); + { + if( pucAlignedHeap == NULL ) + { + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); + } + + /* Check there is enough room left for the allocation. */ + if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && + ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ + { + /* Return the next free byte then increment the index past this + block. */ + pvReturn = pucAlignedHeap + xNextFreeByte; + xNextFreeByte += xWantedSize; + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and + heap_4.c for alternative implementations, and the memory management pages of + http://www.FreeRTOS.org for more information. */ + ( void ) pv; + + /* Force an assert as it is invalid to call this function. */ + configASSERT( pv == NULL ); +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* Only required when static memory is not cleared. */ + xNextFreeByte = ( size_t ) 0; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); +} + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_2.c b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_2.c new file mode 100644 index 0000000..a1a7674 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_2.c @@ -0,0 +1,303 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that permits + * allocated blocks to be freed, but does not combine adjacent free blocks + * into a single larger block (and so will fragment memory). See heap_4.c for + * an equivalent that does combine adjacent blocks into single larger blocks. + * + * See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* + * Initialises the heap structures before their first use. + */ +static void prvHeapInit( void ); + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; + +/* Define the linked list structure. This is used to link free blocks in order +of their size. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + + +static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, xEnd; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE; + +/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ + +/* + * Insert a block into the list of free blocks - which is ordered by size of + * the block. Small blocks at the start of the list and large blocks at the end + * of the list. + */ +#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ +{ \ +BlockLink_t *pxIterator; \ +size_t xBlockSize; \ + \ + xBlockSize = pxBlockToInsert->xBlockSize; \ + \ + /* Iterate through the list until a block is found that has a larger size */ \ + /* than the block we are inserting. */ \ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ + { \ + /* There is nothing to do here - just iterate to the correct position. */ \ + } \ + \ + /* Update the list to include the block being inserted in the correct */ \ + /* position. */ \ + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ + pxIterator->pxNextFreeBlock = pxBlockToInsert; \ +} +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +static BaseType_t xHeapHasBeenInitialised = pdFALSE; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( xHeapHasBeenInitialised == pdFALSE ) + { + prvHeapInit(); + xHeapHasBeenInitialised = pdTRUE; + } + + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += heapSTRUCT_SIZE; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + } + + if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) ) + { + /* Blocks are stored in byte order - traverse the list from the start + (smallest) block until one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If we found the end marker then a block of adequate size was not found. */ + if( pxBlock != &xEnd ) + { + /* Return the memory space - jumping over the BlockLink_t structure + at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); + + /* This block is being returned for use so must be taken out of the + list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new block + following the number of bytes requested. The void cast is + used to prevent byte alignment warnings from the compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the single + block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + } + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= heapSTRUCT_SIZE; + + /* This unexpected casting is to keep some compilers from issuing + byte alignment warnings. */ + pxLink = ( void * ) puc; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + } + ( void ) xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; + + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* xEnd is used to mark the end of the list of free blocks. */ + xEnd.xBlockSize = configADJUSTED_HEAP_SIZE; + xEnd.pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE; + pxFirstFreeBlock->pxNextFreeBlock = &xEnd; +} +/*-----------------------------------------------------------*/ diff --git a/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_3.c b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_3.c new file mode 100644 index 0000000..f3c49c0 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_3.c @@ -0,0 +1,135 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Implementation of pvPortMalloc() and vPortFree() that relies on the + * compilers own malloc() and free() implementations. + * + * This file can only be used if the linker is configured to to generate + * a heap memory area. + * + * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ + +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn; + + vTaskSuspendAll(); + { + pvReturn = malloc( xWantedSize ); + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + if( pv ) + { + vTaskSuspendAll(); + { + free( pv ); + traceFREE( pv, 0 ); + } + ( void ) xTaskResumeAll(); + } +} + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_4.c b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_4.c new file mode 100644 index 0000000..8df0e9a --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_4.c @@ -0,0 +1,474 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that combines + * (coalescences) adjacent memory blocks as they are freed, and in so doing + * limits memory fragmentation. + * + * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize * 2 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Allocate the memory for the heap. */ +#if( configAPPLICATION_ALLOCATED_HEAP == 1 ) + /* The application writer has already defined the array used for the RTOS + heap - probably so it can be placed in a special segment or address. */ + extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +#else + static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +#endif /* configAPPLICATION_ALLOCATED_HEAP */ + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/* + * Called automatically to setup the required heap structures the first time + * pvPortMalloc() is called. + */ +static void prvHeapInit( void ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const size_t xHeapStructSize = ( ( sizeof( BlockLink_t ) + ( ( ( size_t ) portBYTE_ALIGNMENT_MASK ) - ( size_t ) 1 ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ) ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0U; +static size_t xMinimumEverFreeBytesRemaining = 0U; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( pxEnd == NULL ) + { + prvHeapInit(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += xHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + configASSERT( ( ( ( uint32_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + configASSERT( ( ( ( uint32_t ) pvReturn ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; +uint32_t ulAddress; +size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; + + /* Ensure the heap starts on a correctly aligned boundary. */ + ulAddress = ( uint32_t ) ucHeap; + + if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + ulAddress += ( portBYTE_ALIGNMENT - 1 ); + ulAddress &= ~( ( uint32_t ) portBYTE_ALIGNMENT_MASK ); + xTotalHeapSize -= ulAddress - ( uint32_t ) ucHeap; + } + + pucAlignedHeap = ( uint8_t * ) ulAddress; + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* pxEnd is used to mark the end of the list of free blocks and is inserted + at the end of the heap space. */ + ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalHeapSize; + ulAddress -= xHeapStructSize; + ulAddress &= ~( ( uint32_t ) portBYTE_ALIGNMENT_MASK ); + pxEnd = ( void * ) ulAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space, minus the space taken by pxEnd. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlock; + pxFirstFreeBlock->pxNextFreeBlock = pxEnd; + + /* Only one block exists - and it covers the entire usable heap space. */ + xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} + diff --git a/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_5.c b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_5.c new file mode 100644 index 0000000..b7bcaae --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/MemMang/heap_5.c @@ -0,0 +1,523 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() that allows the heap to be defined + * across multiple non-contigous blocks and combines (coalescences) adjacent + * memory blocks as they are freed. + * + * See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative + * implementations, and the memory management pages of http://www.FreeRTOS.org + * for more information. + * + * Usage notes: + * + * vPortDefineHeapRegions() ***must*** be called before pvPortMalloc(). + * pvPortMalloc() will be called if any task objects (tasks, queues, event + * groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be + * called before any other objects are defined. + * + * vPortDefineHeapRegions() takes a single parameter. The parameter is an array + * of HeapRegion_t structures. HeapRegion_t is defined in portable.h as + * + * typedef struct HeapRegion + * { + * uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap. + * size_t xSizeInBytes; << Size of the block of memory. + * } HeapRegion_t; + * + * The array is terminated using a NULL zero sized region definition, and the + * memory regions defined in the array ***must*** appear in address order from + * low address to high address. So the following is a valid example of how + * to use the function. + * + * HeapRegion_t xHeapRegions[] = + * { + * { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000 + * { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000 + * { NULL, 0 } << Terminates the array. + * }; + * + * vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions(). + * + * Note 0x80000000 is the lower address so appears in the array first. + * + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( uxHeapStructSize << 1 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const uint32_t uxHeapStructSize = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0; +static size_t xMinimumEverFreeBytesRemaining = 0; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + /* The heap must be initialised before the first call to + prvPortMalloc(). */ + configASSERT( pxEnd ); + + vTaskSuspendAll(); + { + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += uxHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= uxHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} +/*-----------------------------------------------------------*/ + +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) +{ +BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock; +uint8_t *pucAlignedHeap; +size_t xTotalRegionSize, xTotalHeapSize = 0; +BaseType_t xDefinedRegions = 0; +uint32_t ulAddress; +const HeapRegion_t *pxHeapRegion; + + /* Can only call once! */ + configASSERT( pxEnd == NULL ); + + pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); + + while( pxHeapRegion->xSizeInBytes > 0 ) + { + xTotalRegionSize = pxHeapRegion->xSizeInBytes; + + /* Ensure the heap region starts on a correctly aligned boundary. */ + ulAddress = ( uint32_t ) pxHeapRegion->pucStartAddress; + if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + ulAddress += ( portBYTE_ALIGNMENT - 1 ); + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + + /* Adjust the size for the bytes lost to alignment. */ + xTotalRegionSize -= ulAddress - ( uint32_t ) pxHeapRegion->pucStartAddress; + } + + pucAlignedHeap = ( uint8_t * ) ulAddress; + + /* Set xStart if it has not already been set. */ + if( xDefinedRegions == 0 ) + { + /* xStart is used to hold a pointer to the first item in the list of + free blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + } + else + { + /* Should only get here if one region has already been added to the + heap. */ + configASSERT( pxEnd != NULL ); + + /* Check blocks are passed in with increasing start addresses. */ + configASSERT( ulAddress > ( uint32_t ) pxEnd ); + } + + /* Remember the location of the end marker in the previous region, if + any. */ + pxPreviousFreeBlock = pxEnd; + + /* pxEnd is used to mark the end of the list of free blocks and is + inserted at the end of the region space. */ + ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize; + ulAddress -= uxHeapStructSize; + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + pxEnd = ( BlockLink_t * ) ulAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block in this region that is + sized to take up the entire heap region minus the space taken by the + free block structure. */ + pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap; + pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion; + pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd; + + /* If this is not the first region that makes up the entire heap space + then link the previous region to this region. */ + if( pxPreviousFreeBlock != NULL ) + { + pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion; + } + + xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + + /* Move onto the next HeapRegion_t structure. */ + xDefinedRegions++; + pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); + } + + xMinimumEverFreeBytesRemaining = xTotalHeapSize; + xFreeBytesRemaining = xTotalHeapSize; + + /* Check something was actually defined before it is accessed. */ + configASSERT( xTotalHeapSize ); + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} + diff --git a/STM32F1/libraries/FreeRTOS900/utility/StackMacros.h b/STM32F1/libraries/FreeRTOS900/utility/StackMacros.h new file mode 100644 index 0000000..13c6b82 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/StackMacros.h @@ -0,0 +1,171 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef STACK_MACROS_H +#define STACK_MACROS_H + +/* + * Call the stack overflow hook function if the stack of the task being swapped + * out is currently overflowed, or looks like it might have overflowed in the + * past. + * + * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check + * the current stack state only - comparing the current top of stack value to + * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 + * will also cause the last few stack bytes to be checked to ensure the value + * to which the bytes were set when the task was created have not been + * overwritten. Note this second test does not guarantee that an overflowed + * stack will always be recognised. + */ + +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskCHECK_FOR_STACK_OVERFLOW() \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskCHECK_FOR_STACK_OVERFLOW() \ + { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) + + #define taskCHECK_FOR_STACK_OVERFLOW() \ + { \ + const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ + const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \ + \ + if( ( pulStack[ 0 ] != ulCheckValue ) || \ + ( pulStack[ 1 ] != ulCheckValue ) || \ + ( pulStack[ 2 ] != ulCheckValue ) || \ + ( pulStack[ 3 ] != ulCheckValue ) ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) + + #define taskCHECK_FOR_STACK_OVERFLOW() \ + { \ + int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +/* Remove stack overflow macro if not being used. */ +#ifndef taskCHECK_FOR_STACK_OVERFLOW + #define taskCHECK_FOR_STACK_OVERFLOW() +#endif + + + +#endif /* STACK_MACROS_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/croutine.c b/STM32F1/libraries/FreeRTOS900/utility/croutine.c new file mode 100644 index 0000000..993e09b --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/croutine.c @@ -0,0 +1,395 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "croutine.h" + +/* Remove the whole file is co-routines are not being used. */ +#if( configUSE_CO_ROUTINES != 0 ) + +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + + +/* Lists for ready and blocked co-routines. --------------------*/ +static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ +static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ +static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ +static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ +static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ +static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ + +/* Other file private variables. --------------------------------*/ +CRCB_t * pxCurrentCoRoutine = NULL; +static UBaseType_t uxTopCoRoutineReadyPriority = 0; +static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; + +/* The initial state of the co-routine when it is created. */ +#define corINITIAL_STATE ( 0 ) + +/* + * Place the co-routine represented by pxCRCB into the appropriate ready queue + * for the priority. It is inserted at the end of the list. + * + * This macro accesses the co-routine ready lists and therefore must not be + * used from within an ISR. + */ +#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ +{ \ + if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ + { \ + uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ + } \ + vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ +} + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first co-routine. + */ +static void prvInitialiseCoRoutineLists( void ); + +/* + * Co-routines that are readied by an interrupt cannot be placed directly into + * the ready lists (there is no mutual exclusion). Instead they are placed in + * in the pending ready list in order that they can later be moved to the ready + * list by the co-routine scheduler. + */ +static void prvCheckPendingReadyList( void ); + +/* + * Macro that looks at the list of co-routines that are currently delayed to + * see if any require waking. + * + * Co-routines are stored in the queue in the order of their wake time - + * meaning once one co-routine has been found whose timer has not expired + * we need not look any further down the list. + */ +static void prvCheckDelayedList( void ); + +/*-----------------------------------------------------------*/ + +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) +{ +BaseType_t xReturn; +CRCB_t *pxCoRoutine; + + /* Allocate the memory that will store the co-routine control block. */ + pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); + if( pxCoRoutine ) + { + /* If pxCurrentCoRoutine is NULL then this is the first co-routine to + be created and the co-routine data structures need initialising. */ + if( pxCurrentCoRoutine == NULL ) + { + pxCurrentCoRoutine = pxCoRoutine; + prvInitialiseCoRoutineLists(); + } + + /* Check the priority is within limits. */ + if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) + { + uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; + } + + /* Fill out the co-routine control block from the function parameters. */ + pxCoRoutine->uxState = corINITIAL_STATE; + pxCoRoutine->uxPriority = uxPriority; + pxCoRoutine->uxIndex = uxIndex; + pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; + + /* Initialise all the other co-routine control block parameters. */ + vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); + vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); + + /* Set the co-routine control block as a link back from the ListItem_t. + This is so we can get back to the containing CRCB from a generic item + in a list. */ + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); + + /* Now the co-routine has been initialised it can be added to the ready + list at the correct priority. */ + prvAddCoRoutineToReadyQueue( pxCoRoutine ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) +{ +TickType_t xTimeToWake; + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xCoRoutineTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xCoRoutineTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + + if( pxEventList ) + { + /* Also add the co-routine to an event list. If this is done then the + function must be called with interrupts disabled. */ + vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckPendingReadyList( void ) +{ + /* Are there any co-routines waiting to get moved to the ready list? These + are co-routines that have been readied by an ISR. The ISR cannot access + the ready lists itself. */ + while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) + { + CRCB_t *pxUnblockedCRCB; + + /* The pending ready list can be accessed by an ISR. */ + portDISABLE_INTERRUPTS(); + { + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + } + portENABLE_INTERRUPTS(); + + ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); + prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckDelayedList( void ) +{ +CRCB_t *pxCRCB; + + xPassedTicks = xTaskGetTickCount() - xLastTickCount; + while( xPassedTicks ) + { + xCoRoutineTickCount++; + xPassedTicks--; + + /* If the tick count has overflowed we need to swap the ready lists. */ + if( xCoRoutineTickCount == 0 ) + { + List_t * pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. If there are + any items in pxDelayedCoRoutineList here then there is an error! */ + pxTemp = pxDelayedCoRoutineList; + pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; + pxOverflowDelayedCoRoutineList = pxTemp; + } + + /* See if this tick has made a timeout expire. */ + while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) + { + pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); + + if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) + { + /* Timeout not yet expired. */ + break; + } + + portDISABLE_INTERRUPTS(); + { + /* The event could have occurred just before this critical + section. If this is the case then the generic list item will + have been moved to the pending ready list and the following + line is still valid. Also the pvContainer parameter will have + been set to NULL so the following lines are also valid. */ + ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); + + /* Is the co-routine waiting on an event also? */ + if( pxCRCB->xEventListItem.pvContainer ) + { + ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); + } + } + portENABLE_INTERRUPTS(); + + prvAddCoRoutineToReadyQueue( pxCRCB ); + } + } + + xLastTickCount = xCoRoutineTickCount; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineSchedule( void ) +{ + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); + + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); + + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + { + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } + --uxTopCoRoutineReadyPriority; + } + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + + return; +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseCoRoutineLists( void ) +{ +UBaseType_t uxPriority; + + for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + } + + vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); + + /* Start with pxDelayedCoRoutineList using list1 and the + pxOverflowDelayedCoRoutineList using list2. */ + pxDelayedCoRoutineList = &xDelayedCoRoutineList1; + pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; +} +/*-----------------------------------------------------------*/ + +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) +{ +CRCB_t *pxUnblockedCRCB; +BaseType_t xReturn; + + /* This function is called from within an interrupt. It can only access + event lists and the pending ready list. This function assumes that a + check has already been made to ensure pxEventList is not empty. */ + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + + if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} + +#endif /* configUSE_CO_ROUTINES == 0 */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/croutine.h b/STM32F1/libraries/FreeRTOS900/utility/croutine.h new file mode 100644 index 0000000..4f003a0 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/croutine.h @@ -0,0 +1,762 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef CO_ROUTINE_H +#define CO_ROUTINE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include croutine.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to hide the implementation of the co-routine control block. The +control block structure however has to be included in the header due to +the macro implementation of the co-routine functionality. */ +typedef void * CoRoutineHandle_t; + +/* Defines the prototype to which co-routine functions must conform. */ +typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); + +typedef struct corCoRoutineControlBlock +{ + crCOROUTINE_CODE pxCoRoutineFunction; + ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ + UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + uint16_t uxState; /*< Used internally by the co-routine implementation. */ +} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ + +/** + * croutine. h + *
+ BaseType_t xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 UBaseType_t uxPriority,
+                                 UBaseType_t uxIndex
+                               );
+ * + * Create a new co-routine and add it to the list of co-routines that are + * ready to run. + * + * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine + * functions require special syntax - see the co-routine section of the WEB + * documentation for more information. + * + * @param uxPriority The priority with respect to other co-routines at which + * the co-routine will run. + * + * @param uxIndex Used to distinguish between different co-routines that + * execute the same function. See the example below and the co-routine section + * of the WEB documentation for further information. + * + * @return pdPASS if the co-routine was successfully created and added to a ready + * list, otherwise an error code defined with ProjDefs.h. + * + * Example usage: +
+ // Co-routine to be created.
+ void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how int32_t to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ uint8_t ucParameterToPass;
+ TaskHandle_t xHandle;
+
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   
+ * \defgroup xCoRoutineCreate xCoRoutineCreate + * \ingroup Tasks + */ +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ); + + +/** + * croutine. h + *
+ void vCoRoutineSchedule( void );
+ * + * Run a co-routine. + * + * vCoRoutineSchedule() executes the highest priority co-routine that is able + * to run. The co-routine will execute until it either blocks, yields or is + * preempted by a task. Co-routines execute cooperatively so one + * co-routine cannot be preempted by another, but can be preempted by a task. + * + * If an application comprises of both tasks and co-routines then + * vCoRoutineSchedule should be called from the idle task (in an idle task + * hook). + * + * Example usage: +
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ 
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * \ingroup Tasks + */ +void vCoRoutineSchedule( void ); + +/** + * croutine. h + *
+ crSTART( CoRoutineHandle_t xHandle );
+ * + * This macro MUST always be called at the start of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0: + +/** + * croutine. h + *
+ crEND();
+ * + * This macro MUST always be called at the end of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crEND() } + +/* + * These macros are intended for internal use by the co-routine implementation + * only. The macros should not be used directly by application writers. + */ +#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): +#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): + +/** + * croutine. h + *
+ crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
+ * + * Delay a co-routine for a fixed period of time. + * + * crDELAY can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * @param xHandle The handle of the co-routine to delay. This is the xHandle + * parameter of the co-routine function. + * + * @param xTickToDelay The number of ticks that the co-routine should delay + * for. The actual amount of time this equates to is defined by + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS + * can be used to convert ticks to milliseconds. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crDELAY crDELAY + * \ingroup Tasks + */ +#define crDELAY( xHandle, xTicksToDelay ) \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); + +/** + *
+ crQUEUE_SEND(
+                  CoRoutineHandle_t xHandle,
+                  QueueHandle_t pxQueue,
+                  void *pvItemToQueue,
+                  TickType_t xTicksToWait,
+                  BaseType_t *pxResult
+             )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_SEND can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue on which the data will be posted. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvItemToQueue A pointer to the data being posted onto the queue. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied from pvItemToQueue into the queue + * itself. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for space to become available on the queue, should space not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example + * below). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully posted onto the queue, otherwise it will be set to an + * error defined within ProjDefs.h. + * + * Example usage: +
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xNumberToPost = 0;
+ static BaseType_t xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }
+ * \defgroup crQUEUE_SEND crQUEUE_SEND + * \ingroup Tasks + */ +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_RECEIVE(
+                     CoRoutineHandle_t xHandle,
+                     QueueHandle_t pxQueue,
+                     void *pvBuffer,
+                     TickType_t xTicksToWait,
+                     BaseType_t *pxResult
+                 )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_RECEIVE can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue from which the data will be received. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvBuffer The buffer into which the received item is to be copied. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied into pvBuffer. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for data to become available from the queue, should data not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the + * crQUEUE_SEND example). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully retrieved from the queue, otherwise it will be set to + * an error code as defined within ProjDefs.h. + * + * Example usage: +
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xResult;
+ static UBaseType_t uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ + } \ + if( *( pxResult ) == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *( pxResult ) = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvItemToQueue,
+                            BaseType_t xCoRoutinePreviouslyWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue + * that is being used from within a co-routine. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto + * the same queue multiple times from a single interrupt. The first call + * should always pass in pdFALSE. Subsequent calls should pass in + * the value returned from the previous call. + * + * @return pdTRUE if a co-routine was woken by posting onto the queue. This is + * used by the ISR to determine if a context switch may be required following + * the ISR. + * + * Example usage: +
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ char cRxedChar;
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) + + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvBuffer,
+                            BaseType_t * pxCoRoutineWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data + * from a queue that is being used from within a co-routine (a co-routine + * posted to the queue). + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvBuffer A pointer to a buffer into which the received item will be + * placed. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from the queue into + * pvBuffer. + * + * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become + * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a + * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise + * *pxCoRoutineWoken will remain unchanged. + * + * @return pdTRUE an item was successfully received from the queue, otherwise + * pdFALSE. + * + * Example usage: +
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) + +/* + * This function is intended for internal use by the co-routine macros only. + * The macro nature of the co-routine implementation requires that the + * prototype appears here. The function should not be used by application + * writers. + * + * Removes the current co-routine from its ready list and places it in the + * appropriate delayed list. + */ +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ); + +/* + * This function is intended for internal use by the queue implementation only. + * The function should not be used by application writers. + * + * Removes the highest priority co-routine from the event list and places it in + * the pending ready list. + */ +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ); + +#ifdef __cplusplus +} +#endif + +#endif /* CO_ROUTINE_H */ diff --git a/STM32F1/libraries/FreeRTOS900/utility/deprecated_definitions.h b/STM32F1/libraries/FreeRTOS900/utility/deprecated_definitions.h new file mode 100644 index 0000000..7c6721c --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/deprecated_definitions.h @@ -0,0 +1,321 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef DEPRECATED_DEFINITIONS_H +#define DEPRECATED_DEFINITIONS_H + + +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. The +definitions below remain in the code for backward compatibility only. New +projects should not use them. */ + +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef GCC_MEGA_AVR + #include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR + #include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT + #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT + #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" +#endif + +#ifdef _FEDPICC + #include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +#ifdef GCC_ARM7 + #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +#endif + +#ifdef GCC_ARM7_ECLIPSE + #include "portmacro.h" +#endif + +#ifdef ROWLEY_LPC23xx + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" +#endif + +#ifdef IAR_MSP430 + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S + #include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 + #include "portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 + #include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 + #include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef __GNUC__ + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif +#endif + +#ifdef __ICCAVR32__ + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif +#endif + +#ifdef __91467D + #include "portmacro.h" +#endif + +#ifdef __96340 + #include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#endif /* DEPRECATED_DEFINITIONS_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/event_groups.c b/STM32F1/libraries/FreeRTOS900/utility/event_groups.c new file mode 100644 index 0000000..b8df5fd --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/event_groups.c @@ -0,0 +1,752 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "event_groups.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +/* The following bit fields convey control information in a task's event list +item value. It is important they don't clash with the +taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ +#if configUSE_16_BIT_TICKS == 1 + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U + #define eventWAIT_FOR_ALL_BITS 0x0400U + #define eventEVENT_BITS_CONTROL_BYTES 0xff00U +#else + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL + #define eventWAIT_FOR_ALL_BITS 0x04000000UL + #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL +#endif + +typedef struct xEventGroupDefinition +{ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ + #endif +} EventGroup_t; + +/*-----------------------------------------------------------*/ + +/* + * Test the bits set in uxCurrentEventBits to see if the wait condition is met. + * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is + * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor + * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the + * wait condition is met if any of the bits set in uxBitsToWait for are also set + * in uxCurrentEventBits. + */ +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) + { + EventGroup_t *pxEventBits; + + /* A StaticEventGroup_t object must be provided. */ + configASSERT( pxEventGroupBuffer ); + + /* The user has provided a statically allocated event group - use it. */ + pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ + + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Both static and dynamic allocation can be used, so note that + this event group was created statically in case the event group + is later deleted. */ + pxEventBits->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); + } + + return ( EventGroupHandle_t ) pxEventBits; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + EventGroupHandle_t xEventGroupCreate( void ) + { + EventGroup_t *pxEventBits; + + /* Allocate the event group. */ + pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); + + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Both static and dynamic allocation can be used, so note this + event group was allocated statically in case the event group is + later deleted. */ + pxEventBits->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); + } + + return ( EventGroupHandle_t ) pxEventBits; + } + +#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) +{ +EventBits_t uxOriginalBitValue, uxReturn; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + uxOriginalBitValue = pxEventBits->uxEventBits; + + ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); + + if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + /* All the rendezvous bits are now set - no need to block. */ + uxReturn = ( uxOriginalBitValue | uxBitsToSet ); + + /* Rendezvous always clear the bits. They will have been cleared + already unless this is the only task in the rendezvous. */ + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + + xTicksToWait = 0; + } + else + { + if( xTicksToWait != ( TickType_t ) 0 ) + { + traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); + + /* This assignment is obsolete as uxReturn will get set after + the task unblocks, but some compilers mistakenly generate a + warning about uxReturn being returned without being set if the + assignment is omitted. */ + uxReturn = 0; + } + else + { + /* The rendezvous bits were not set, but no block time was + specified - just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + } + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + /* The task timed out, just return the current event bit value. */ + taskENTER_CRITICAL(); + { + uxReturn = pxEventBits->uxEventBits; + + /* Although the task got here because it timed out before the + bits it was waiting for were set, it is possible that since it + unblocked another task has set the bits. If this is the case + then it needs to clear the bits before exiting. */ + if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + xTimeoutOccurred = pdTRUE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* Control bits might be set as the task had blocked should not be + returned. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + + traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn, uxControlBits = 0; +BaseType_t xWaitConditionMet, xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + /* Check the user is not attempting to wait on the bits used by the kernel + itself, and that at least one bit is being requested. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; + + /* Check to see if the wait condition is already met or not. */ + xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); + + if( xWaitConditionMet != pdFALSE ) + { + /* The wait condition has already been met so there is no need to + block. */ + uxReturn = uxCurrentEventBits; + xTicksToWait = ( TickType_t ) 0; + + /* Clear the wait bits if requested to do so. */ + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The wait condition has not been met, but no block time was + specified, so just return the current value. */ + uxReturn = uxCurrentEventBits; + } + else + { + /* The task is going to block to wait for its required bits to be + set. uxControlBits are used to remember the specified behaviour of + this call to xEventGroupWaitBits() - for use when the event bits + unblock the task. */ + if( xClearOnExit != pdFALSE ) + { + uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xWaitForAllBits != pdFALSE ) + { + uxControlBits |= eventWAIT_FOR_ALL_BITS; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); + + /* This is obsolete as it will get set after the task unblocks, but + some compilers mistakenly generate a warning about the variable + being returned without being set if it is not done. */ + uxReturn = 0; + + traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + taskENTER_CRITICAL(); + { + /* The task timed out, just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + + /* It is possible that the event bits were updated between this + task leaving the Blocked state and running again. */ + if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) + { + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + /* Prevent compiler warnings when trace macros are not used. */ + xTimeoutOccurred = pdFALSE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* The task blocked so control bits may have been set. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + /* Check the user is not attempting to clear the bits used by the kernel + itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + taskENTER_CRITICAL(); + { + traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); + + /* The value returned is the event group value prior to the bits being + cleared. */ + uxReturn = pxEventBits->uxEventBits; + + /* Clear the bits. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) +{ +UBaseType_t uxSavedInterruptStatus; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + uxReturn = pxEventBits->uxEventBits; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) +{ +ListItem_t *pxListItem, *pxNext; +ListItem_t const *pxListEnd; +List_t *pxList; +EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xMatchFound = pdFALSE; + + /* Check the user is not attempting to set the bits used by the kernel + itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + pxList = &( pxEventBits->xTasksWaitingForBits ); + pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + vTaskSuspendAll(); + { + traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); + + pxListItem = listGET_HEAD_ENTRY( pxList ); + + /* Set the bits. */ + pxEventBits->uxEventBits |= uxBitsToSet; + + /* See if the new bit value should unblock any tasks. */ + while( pxListItem != pxListEnd ) + { + pxNext = listGET_NEXT( pxListItem ); + uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); + xMatchFound = pdFALSE; + + /* Split the bits waited for from the control bits. */ + uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; + uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; + + if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) + { + /* Just looking for single bit being set. */ + if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) + { + xMatchFound = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) + { + /* All bits are set. */ + xMatchFound = pdTRUE; + } + else + { + /* Need all bits to be set, but not all the bits were set. */ + } + + if( xMatchFound != pdFALSE ) + { + /* The bits match. Should the bits be cleared on exit? */ + if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) + { + uxBitsToClear |= uxBitsWaitedFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the actual event flag value in the task's event list + item before removing the task from the event list. The + eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows + that is was unblocked due to its required bits matching, rather + than because it timed out. */ + ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + /* Move onto the next list item. Note pxListItem->pxNext is not + used here as the list item may have been removed from the event list + and inserted into the ready/pending reading list. */ + pxListItem = pxNext; + } + + /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT + bit was set in the control word. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + ( void ) xTaskResumeAll(); + + return pxEventBits->uxEventBits; +} +/*-----------------------------------------------------------*/ + +void vEventGroupDelete( EventGroupHandle_t xEventGroup ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + + vTaskSuspendAll(); + { + traceEVENT_GROUP_DELETE( xEventGroup ); + + while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) + { + /* Unblock the task, returning 0 as the event list is being deleted + and cannot therefore have any bits set. */ + configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); + ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The event group can only have been allocated dynamically - free + it again. */ + vPortFree( pxEventBits ); + } + #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The event group could have been allocated statically or + dynamically, so check before attempting to free the memory. */ + if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxEventBits ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + } + ( void ) xTaskResumeAll(); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'set bits' command that was pended from +an interrupt. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) +{ + ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'clear bits' command that was pended from +an interrupt. */ +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) +{ + ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) +{ +BaseType_t xWaitConditionMet = pdFALSE; + + if( xWaitForAllBits == pdFALSE ) + { + /* Task only has to wait for one bit within uxBitsToWaitFor to be + set. Is one already set? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Task has to wait for all the bits in uxBitsToWaitFor to be set. + Are they set already? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return xWaitConditionMet; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if (configUSE_TRACE_FACILITY == 1) + + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) + { + UBaseType_t xReturn; + EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; + + if( xEventGroup == NULL ) + { + xReturn = 0; + } + else + { + xReturn = pxEventBits->uxEventGroupNumber; + } + + return xReturn; + } + +#endif + diff --git a/STM32F1/libraries/FreeRTOS900/utility/event_groups.h b/STM32F1/libraries/FreeRTOS900/utility/event_groups.h new file mode 100644 index 0000000..7331c91 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/event_groups.h @@ -0,0 +1,797 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef EVENT_GROUPS_H +#define EVENT_GROUPS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" +#endif + +/* FreeRTOS includes. */ +#include "timers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * An event group is a collection of bits to which an application can assign a + * meaning. For example, an application may create an event group to convey + * the status of various CAN bus related events in which bit 0 might mean "A CAN + * message has been received and is ready for processing", bit 1 might mean "The + * application has queued a message that is ready for sending onto the CAN + * network", and bit 2 might mean "It is time to send a SYNC message onto the + * CAN network" etc. A task can then test the bit values to see which events + * are active, and optionally enter the Blocked state to wait for a specified + * bit or a group of specified bits to be active. To continue the CAN bus + * example, a CAN controlling task can enter the Blocked state (and therefore + * not consume any processing time) until either bit 0, bit 1 or bit 2 are + * active, at which time the bit that was actually active would inform the task + * which action it had to take (process a received message, send a message, or + * send a SYNC). + * + * The event groups implementation contains intelligence to avoid race + * conditions that would otherwise occur were an application to use a simple + * variable for the same purpose. This is particularly important with respect + * to when a bit within an event group is to be cleared, and when bits have to + * be set and then tested atomically - as is the case where event groups are + * used to create a synchronisation point between multiple tasks (a + * 'rendezvous'). + * + * \defgroup EventGroup + */ + + + +/** + * event_groups.h + * + * Type by which event groups are referenced. For example, a call to + * xEventGroupCreate() returns an EventGroupHandle_t variable that can then + * be used as a parameter to other event group functions. + * + * \defgroup EventGroupHandle_t EventGroupHandle_t + * \ingroup EventGroup + */ +typedef void * EventGroupHandle_t; + +/* + * The type that holds event bits always matches TickType_t - therefore the + * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, + * 32 bits if set to 0. + * + * \defgroup EventBits_t EventBits_t + * \ingroup EventGroup + */ +typedef TickType_t EventBits_t; + +/** + * event_groups.h + *
+ EventGroupHandle_t xEventGroupCreate( void );
+ 
+ * + * Create a new event group. + * + * Internally, within the FreeRTOS implementation, event groups use a [small] + * block of memory, in which the event group's structure is stored. If an event + * groups is created using xEventGropuCreate() then the required memory is + * automatically dynamically allocated inside the xEventGroupCreate() function. + * (see http://www.freertos.org/a00111.html). If an event group is created + * using xEventGropuCreateStatic() then the application writer must instead + * provide the memory that will get used by the event group. + * xEventGroupCreateStatic() therefore allows an event group to be created + * without using any dynamic memory allocation. + * + * Although event groups are not related to ticks, for internal implementation + * reasons the number of bits available for use in an event group is dependent + * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If + * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit + * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has + * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store + * event bits within an event group. + * + * @return If the event group was created then a handle to the event group is + * returned. If there was insufficient FreeRTOS heap available to create the + * event group then NULL is returned. See http://www.freertos.org/a00111.html + * + * Example usage: +
+	// Declare a variable to hold the created event group.
+	EventGroupHandle_t xCreatedEventGroup;
+
+	// Attempt to create the event group.
+	xCreatedEventGroup = xEventGroupCreate();
+
+	// Was the event group created successfully?
+	if( xCreatedEventGroup == NULL )
+	{
+		// The event group was not created because there was insufficient
+		// FreeRTOS heap available.
+	}
+	else
+	{
+		// The event group was created.
+	}
+   
+ * \defgroup xEventGroupCreate xEventGroupCreate + * \ingroup EventGroup + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; +#endif + +/** + * event_groups.h + *
+ EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
+ 
+ * + * Create a new event group. + * + * Internally, within the FreeRTOS implementation, event groups use a [small] + * block of memory, in which the event group's structure is stored. If an event + * groups is created using xEventGropuCreate() then the required memory is + * automatically dynamically allocated inside the xEventGroupCreate() function. + * (see http://www.freertos.org/a00111.html). If an event group is created + * using xEventGropuCreateStatic() then the application writer must instead + * provide the memory that will get used by the event group. + * xEventGroupCreateStatic() therefore allows an event group to be created + * without using any dynamic memory allocation. + * + * Although event groups are not related to ticks, for internal implementation + * reasons the number of bits available for use in an event group is dependent + * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If + * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit + * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has + * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store + * event bits within an event group. + * + * @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type + * StaticEventGroup_t, which will be then be used to hold the event group's data + * structures, removing the need for the memory to be allocated dynamically. + * + * @return If the event group was created then a handle to the event group is + * returned. If pxEventGroupBuffer was NULL then NULL is returned. + * + * Example usage: +
+	// StaticEventGroup_t is a publicly accessible structure that has the same
+	// size and alignment requirements as the real event group structure.  It is
+	// provided as a mechanism for applications to know the size of the event
+	// group (which is dependent on the architecture and configuration file
+	// settings) without breaking the strict data hiding policy by exposing the
+	// real event group internals.  This StaticEventGroup_t variable is passed
+	// into the xSemaphoreCreateEventGroupStatic() function and is used to store
+	// the event group's data structures
+	StaticEventGroup_t xEventGroupBuffer;
+
+	// Create the event group without dynamically allocating any memory.
+	xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
+   
+ */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION; +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupWaitBits( 	EventGroupHandle_t xEventGroup,
+										const EventBits_t uxBitsToWaitFor,
+										const BaseType_t xClearOnExit,
+										const BaseType_t xWaitForAllBits,
+										const TickType_t xTicksToWait );
+ 
+ * + * [Potentially] block to wait for one or more bits to be set within a + * previously created event group. + * + * This function cannot be called from an interrupt. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and/or bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within + * uxBitsToWaitFor that are set within the event group will be cleared before + * xEventGroupWaitBits() returns if the wait condition was met (if the function + * returns for a reason other than a timeout). If xClearOnExit is set to + * pdFALSE then the bits set in the event group are not altered when the call to + * xEventGroupWaitBits() returns. + * + * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then + * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor + * are set or the specified block time expires. If xWaitForAllBits is set to + * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set + * in uxBitsToWaitFor is set or the specified block time expires. The block + * time is specified by the xTicksToWait parameter. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for one/all (depending on the xWaitForAllBits value) of the bits specified by + * uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupWaitBits() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupWaitBits() returned because the bits it was waiting for were set + * then the returned value is the event group value before any bits were + * automatically cleared in the case that xClearOnExit parameter was set to + * pdTRUE. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+   const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+		// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
+		// the event group.  Clear the bits before exiting.
+		uxBits = xEventGroupWaitBits(
+					xEventGroup,	// The event group being tested.
+					BIT_0 | BIT_4,	// The bits within the event group to wait for.
+					pdTRUE,			// BIT_0 and BIT_4 should be cleared before returning.
+					pdFALSE,		// Don't wait for both bits, either bit will do.
+					xTicksToWait );	// Wait a maximum of 100ms for either bit to be set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// xEventGroupWaitBits() returned because both bits were set.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_0 was set.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_4 was set.
+		}
+		else
+		{
+			// xEventGroupWaitBits() returned because xTicksToWait ticks passed
+			// without either BIT_0 or BIT_4 becoming set.
+		}
+   }
+   
+ * \defgroup xEventGroupWaitBits xEventGroupWaitBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+ 
+ * + * Clear bits within an event group. This function cannot be called from an + * interrupt. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear + * in the event group. For example, to clear bit 3 only, set uxBitsToClear to + * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09. + * + * @return The value of the event group before the specified bits were cleared. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Clear bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupClearBits(
+								xEventGroup,	// The event group being updated.
+								BIT_0 | BIT_4 );// The bits being cleared.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
+			// called.  Both will now be clear (not set).
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 were set in the first place.
+		}
+   }
+   
+ * \defgroup xEventGroupClearBits xEventGroupClearBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * A version of xEventGroupClearBits() that can be called from an interrupt. + * + * Setting bits in an event group is not a deterministic operation because there + * are an unknown number of tasks that may be waiting for the bit or bits being + * set. FreeRTOS does not allow nondeterministic operations to be performed + * while interrupts are disabled, so protects event groups that are accessed + * from tasks by suspending the scheduler rather than disabling interrupts. As + * a result event groups cannot be accessed directly from an interrupt service + * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the + * timer task to have the clear operation performed in the context of the timer + * task. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. + * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3 + * and bit 0 set uxBitsToClear to 0x09. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+		// Clear bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupClearBitsFromISR(
+							xEventGroup,	 // The event group being updated.
+							BIT_0 | BIT_4 ); // The bits being set.
+
+		if( xResult == pdPASS )
+		{
+			// The message was posted successfully.
+		}
+  }
+   
+ * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; +#else + #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * Set bits within an event group. + * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() + * is a version that can be called from an interrupt. + * + * Setting bits in an event group will automatically unblock tasks that are + * blocked waiting for the bits. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @return The value of the event group at the time the call to + * xEventGroupSetBits() returns. There are two reasons why the returned value + * might have the bits specified by the uxBitsToSet parameter cleared. First, + * if setting a bit results in a task that was waiting for the bit leaving the + * blocked state then it is possible the bit will be cleared automatically + * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any + * unblocked (or otherwise Ready state) task that has a priority above that of + * the task that called xEventGroupSetBits() will execute and may change the + * event group value before the call to xEventGroupSetBits() returns. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupSetBits(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4 );// The bits being set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 remained set when the function returned.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 remained set when the function returned, but bit 4 was
+			// cleared.  It might be that bit 4 was cleared automatically as a
+			// task that was waiting for bit 4 was removed from the Blocked
+			// state.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 remained set when the function returned, but bit 0 was
+			// cleared.  It might be that bit 0 was cleared automatically as a
+			// task that was waiting for bit 0 was removed from the Blocked
+			// state.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 remained set.  It might be that a task
+			// was waiting for both of the bits to be set, and the bits were
+			// cleared as the task left the Blocked state.
+		}
+   }
+   
+ * \defgroup xEventGroupSetBits xEventGroupSetBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
+ 
+ * + * A version of xEventGroupSetBits() that can be called from an interrupt. + * + * Setting bits in an event group is not a deterministic operation because there + * are an unknown number of tasks that may be waiting for the bit or bits being + * set. FreeRTOS does not allow nondeterministic operations to be performed in + * interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR() + * sends a message to the timer task to have the set operation performed in the + * context of the timer task - where a scheduler lock is used in place of a + * critical section. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task is higher than the priority of the + * currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE by + * xEventGroupSetBitsFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+   BaseType_t xHigherPriorityTaskWoken, xResult;
+
+		// xHigherPriorityTaskWoken must be initialised to pdFALSE.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupSetBitsFromISR(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4   // The bits being set.
+							&xHigherPriorityTaskWoken );
+
+		// Was the message posted successfully?
+		if( xResult == pdPASS )
+		{
+			// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
+			// switch should be requested.  The macro used is port specific and
+			// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+			// refer to the documentation page for the port being used.
+			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+		}
+  }
+   
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#else + #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSync(	EventGroupHandle_t xEventGroup,
+									const EventBits_t uxBitsToSet,
+									const EventBits_t uxBitsToWaitFor,
+									TickType_t xTicksToWait );
+ 
+ * + * Atomically set bits within an event group, then wait for a combination of + * bits to be set within the same event group. This functionality is typically + * used to synchronise multiple tasks, where each task has to wait for the other + * tasks to reach a synchronisation point before proceeding. + * + * This function cannot be used from an interrupt. + * + * The function will return before its block time expires if the bits specified + * by the uxBitsToWait parameter are set, or become set within that time. In + * this case all the bits specified by uxBitsToWait will be automatically + * cleared before the function returns. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToSet The bits to set in the event group before determining + * if, and possibly waiting for, all the bits specified by the uxBitsToWait + * parameter are set. + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for all of the bits specified by uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupSync() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupSync() returned because all the bits it was waiting for were + * set then the returned value is the event group value before any bits were + * automatically cleared. + * + * Example usage: +
+ // Bits used by the three tasks.
+ #define TASK_0_BIT		( 1 << 0 )
+ #define TASK_1_BIT		( 1 << 1 )
+ #define TASK_2_BIT		( 1 << 2 )
+
+ #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+
+ // Use an event group to synchronise three tasks.  It is assumed this event
+ // group has already been created elsewhere.
+ EventGroupHandle_t xEventBits;
+
+ void vTask0( void *pvParameters )
+ {
+ EventBits_t uxReturn;
+ TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 0 in the event flag to note this task has reached the
+		// sync point.  The other two tasks will set the other two bits defined
+		// by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
+		// point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
+		// for this to happen.
+		uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
+
+		if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
+		{
+			// All three tasks reached the synchronisation point before the call
+			// to xEventGroupSync() timed out.
+		}
+	}
+ }
+
+ void vTask1( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 1 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	 }
+ }
+
+ void vTask2( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 2 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	}
+ }
+
+ 
+ * \defgroup xEventGroupSync xEventGroupSync + * \ingroup EventGroup + */ +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
+ 
+ * + * Returns the current value of the bits in an event group. This function + * cannot be used from an interrupt. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBits() was called. + * + * \defgroup xEventGroupGetBits xEventGroupGetBits + * \ingroup EventGroup + */ +#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
+ 
+ * + * A version of xEventGroupGetBits() that can be called from an ISR. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. + * + * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR + * \ingroup EventGroup + */ +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	void xEventGroupDelete( EventGroupHandle_t xEventGroup );
+ 
+ * + * Delete an event group that was previously created by a call to + * xEventGroupCreate(). Tasks that are blocked on the event group will be + * unblocked and obtain 0 as the event group's value. + * + * @param xEventGroup The event group being deleted. + */ +void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; + +/* For internal use only. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; + + +#if (configUSE_TRACE_FACILITY == 1) + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT_GROUPS_H */ + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/heap_1.c b/STM32F1/libraries/FreeRTOS900/utility/heap_1.c new file mode 100644 index 0000000..178ff7c --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/heap_1.c @@ -0,0 +1,174 @@ +/* + FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * The simplest possible implementation of pvPortMalloc(). Note that this + * implementation does NOT allow allocated memory to be freed again. + * + * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +static size_t xNextFreeByte = ( size_t ) 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn = NULL; +static uint8_t *pucAlignedHeap = NULL; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + #if portBYTE_ALIGNMENT != 1 + if( xWantedSize & portBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + #endif + + vTaskSuspendAll(); + { + if( pucAlignedHeap == NULL ) + { + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); + } + + /* Check there is enough room left for the allocation. */ + if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && + ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ + { + /* Return the next free byte then increment the index past this + block. */ + pvReturn = pucAlignedHeap + xNextFreeByte; + xNextFreeByte += xWantedSize; + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and + heap_4.c for alternative implementations, and the memory management pages of + http://www.FreeRTOS.org for more information. */ + ( void ) pv; + + /* Force an assert as it is invalid to call this function. */ + configASSERT( pv == NULL ); +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* Only required when static memory is not cleared. */ + xNextFreeByte = ( size_t ) 0; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); +} + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/list.c b/STM32F1/libraries/FreeRTOS900/utility/list.c new file mode 100644 index 0000000..5e207c1 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/list.c @@ -0,0 +1,240 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#include +#include "FreeRTOS.h" +#include "list.h" + +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +void vListInitialise( List_t * const pxList ) +{ + /* The list structure contains a list item which is used to mark the + end of the list. To initialise the list the list end is inserted + as the only list entry. */ + pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + /* The list end value is the highest possible value in the list to + ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; + + /* The list end next and previous pointers point to itself so we know + when the list is empty. */ + pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + pxList->uxNumberOfItems = ( UBaseType_t ) 0U; + + /* Write known values into the list if + configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); + listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); +} +/*-----------------------------------------------------------*/ + +void vListInitialiseItem( ListItem_t * const pxItem ) +{ + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pvContainer = NULL; + + /* Write known values into the list item if + configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); + listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); +} +/*-----------------------------------------------------------*/ + +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) +{ +ListItem_t * const pxIndex = pxList->pxIndex; + + /* Only effective when configASSERT() is also defined, these tests may catch + the list data structures being overwritten in memory. They will not catch + data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); + + /* Insert a new list item into pxList, but rather than sort the list, + makes the new list item the last item to be removed by a call to + listGET_OWNER_OF_NEXT_ENTRY(). */ + pxNewListItem->pxNext = pxIndex; + pxNewListItem->pxPrevious = pxIndex->pxPrevious; + + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); + + pxIndex->pxPrevious->pxNext = pxNewListItem; + pxIndex->pxPrevious = pxNewListItem; + + /* Remember which list the item is in. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) +{ +ListItem_t *pxIterator; +const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; + + /* Only effective when configASSERT() is also defined, these tests may catch + the list data structures being overwritten in memory. They will not catch + data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); + + /* Insert the new list item into the list, sorted in xItemValue order. + + If the list already contains a list item with the same item value then the + new list item should be placed after it. This ensures that TCB's which are + stored in ready lists (all of which have the same xItemValue value) get a + share of the CPU. However, if the xItemValue is the same as the back marker + the iteration loop below will not end. Therefore the value is checked + first, and the algorithm slightly modified if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + If you find your application is crashing here then likely causes are + listed below. In addition see http://www.freertos.org/FAQHelp.html for + more tips, and ensure configASSERT() is defined! + http://www.freertos.org/a00110.html#configASSERT + + 1) Stack overflow - + see http://www.freertos.org/Stacks-and-stack-overflow-checking.html + 2) Incorrect interrupt priority assignment, especially on Cortex-M + parts where numerically high priority values denote low actual + interrupt priorities, which can seem counter intuitive. See + http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition + of configMAX_SYSCALL_INTERRUPT_PRIORITY on + http://www.freertos.org/a00110.html + 3) Calling an API function from within a critical section or when + the scheduler is suspended, or calling an API function that does + not end in "FromISR" from an interrupt. + 4) Using a queue or semaphore before it has been initialised or + before the scheduler has been started (are interrupts firing + before vTaskStartScheduler() has been called?). + **********************************************************************/ + + for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + { + /* There is nothing to do here, just iterating to the wanted + insertion position. */ + } + } + + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = pxNewListItem; + + /* Remember which list the item is in. This allows fast removal of the + item later. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) +{ +/* The list item knows which list it is in. Obtain the list from the list +item. */ +List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); + + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxItemToRemove->pvContainer = NULL; + ( pxList->uxNumberOfItems )--; + + return pxList->uxNumberOfItems; +} +/*-----------------------------------------------------------*/ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/list.h b/STM32F1/libraries/FreeRTOS900/utility/list.h new file mode 100644 index 0000000..a080d27 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/list.h @@ -0,0 +1,453 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + +#ifndef INC_FREERTOS_H + #error FreeRTOS.h must be included before list.h +#endif + +#ifndef LIST_H +#define LIST_H + +/* + * The list structure members are modified from within interrupts, and therefore + * by rights should be declared volatile. However, they are only modified in a + * functionally atomic way (within critical sections of with the scheduler + * suspended) and are either passed by reference into a function or indexed via + * a volatile variable. Therefore, in all use cases tested so far, the volatile + * qualifier can be omitted in order to provide a moderate performance + * improvement without adversely affecting functional behaviour. The assembly + * instructions generated by the IAR, ARM and GCC compilers when the respective + * compiler's options were set for maximum optimisation has been inspected and + * deemed to be as intended. That said, as compiler technology advances, and + * especially if aggressive cross module optimisation is used (a use case that + * has not been exercised to any great extend) then it is feasible that the + * volatile qualifier will be needed for correct optimisation. It is expected + * that a compiler removing essential code because, without the volatile + * qualifier on the list structure members and with aggressive cross module + * optimisation, the compiler deemed the code unnecessary will result in + * complete and obvious failure of the scheduler. If this is ever experienced + * then the volatile qualifier can be inserted in the relevant places within the + * list structures by simply defining configLIST_VOLATILE to volatile in + * FreeRTOSConfig.h (as per the example at the bottom of this comment block). + * If configLIST_VOLATILE is not defined then the preprocessor directives below + * will simply #define configLIST_VOLATILE away completely. + * + * To use volatile list structure members then add the following line to + * FreeRTOSConfig.h (without the quotes): + * "#define configLIST_VOLATILE volatile" + */ +#ifndef configLIST_VOLATILE + #define configLIST_VOLATILE +#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macros that can be used to place known values within the list structures, +then check that the known values do not get corrupted during the execution of +the application. These may catch the list data structures being overwritten in +memory. They will not catch data errors caused by incorrect configuration or +use of FreeRTOS.*/ +#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) + /* Define the macros to do nothing. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) + #define listTEST_LIST_INTEGRITY( pxList ) +#else + /* Define macros that add new members into the list structures. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; + + /* Define macros that set the new structure members to known values. */ + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + + /* Define macros that will assert if one of the structure members does not + contain its expected value. */ + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) + #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) +#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ + + +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM +{ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ + listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +}; +typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM +{ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; + struct xLIST_ITEM * configLIST_VOLATILE pxNext; + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; +}; +typedef struct xMINI_LIST_ITEM MiniListItem_t; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST +{ + listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE UBaseType_t uxNumberOfItems; + ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ + listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +} List_t; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) + +/* + * Access macro to get the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) + +/* + * Access macro to retrieve the value of the list item. The value can + * represent anything - for example the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro to retrieve the value of the list item at the head of a given + * list. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_NEXT listGET_NEXT + * \ingroup LinkedList + */ +#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) + +/* + * Return the list item that marks the end of the list + * + * \page listGET_END_MARKER listGET_END_MARKER + * \ingroup LinkedList + */ +#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entry's pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxTCB pxTCB is set to the address of the owner of the next list item. + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +List_t * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE if the list item is in the list, otherwise pdFALSE. + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) + +/* + * Return the list a list item is contained within (referenced from). + * + * @param pxListItem The list item being queried. + * @return A pointer to the List_t object that references the pxListItem + */ +#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) + +/* + * This provides a crude means of knowing if a list has been initialised, as + * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() + * function. + */ +#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION; + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pxIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pxIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param uxListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * @return The number of items that remain in the list after the list item has + * been removed. + * + * \page uxListRemove uxListRemove + * \ingroup LinkedList + */ +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/STM32F1/libraries/FreeRTOS900/utility/mpu_prototypes.h b/STM32F1/libraries/FreeRTOS900/utility/mpu_prototypes.h new file mode 100644 index 0000000..8f7500b --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/mpu_prototypes.h @@ -0,0 +1,177 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * When the MPU is used the standard (non MPU) API functions are mapped to + * equivalents that start "MPU_", the prototypes for which are defined in this + * header files. This will cause the application code to call the MPU_ version + * which wraps the non-MPU version with privilege promoting then demoting code, + * so the kernel code always runs will full privileges. + */ + + +#ifndef MPU_PROTOTYPES_H +#define MPU_PROTOTYPES_H + +/* MPU versions of tasks.h API function. */ +BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ); +TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ); +BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); +void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ); +void MPU_vTaskDelay( const TickType_t xTicksToDelay ); +void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ); +BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ); +UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t xTask ); +eTaskState MPU_eTaskGetState( TaskHandle_t xTask ); +void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ); +void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); +void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ); +void MPU_vTaskResume( TaskHandle_t xTaskToResume ); +void MPU_vTaskStartScheduler( void ); +void MPU_vTaskSuspendAll( void ); +BaseType_t MPU_xTaskResumeAll( void ); +TickType_t MPU_xTaskGetTickCount( void ); +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ); +char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ); +TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery ); +UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); +void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ); +TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ); +void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ); +void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ); +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); +TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ); +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ); +void MPU_vTaskList( char * pcWriteBuffer ); +void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ); +BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ); +BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); +uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); +BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ); +BaseType_t MPU_xTaskIncrementTick( void ); +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ); +void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); +BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ); +void MPU_vTaskMissedYield( void ); +BaseType_t MPU_xTaskGetSchedulerState( void ); + +/* MPU versions of queue.h API function. */ +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ); +BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ); +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ); +UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ); +void MPU_vQueueDelete( QueueHandle_t xQueue ); +QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ); +QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ); +QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ); +QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ); +void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ); +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ); +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ); +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ); +void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ); +const char * MPU_pcQueueGetName( QueueHandle_t xQueue ); +QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ); +QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ); +QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ); +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ); +BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ); +void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ); +UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ); +uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ); + +/* MPU versions of timers.h API function. */ +TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ); +TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer ); +void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ); +void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); +BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ); +TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ); +BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ); +const char * MPU_pcTimerGetName( TimerHandle_t xTimer ); +TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ); +TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ); +BaseType_t MPU_xTimerCreateTimerTask( void ); +BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ); + +/* MPU versions of event_group.h API function. */ +EventGroupHandle_t MPU_xEventGroupCreate( void ); +EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ); +EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ); +EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); +EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); +EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ); +void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ); +UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup ); + +#endif /* MPU_PROTOTYPES_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/mpu_wrappers.h b/STM32F1/libraries/FreeRTOS900/utility/mpu_wrappers.h new file mode 100644 index 0000000..78f5a9a --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/mpu_wrappers.h @@ -0,0 +1,201 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef MPU_WRAPPERS_H +#define MPU_WRAPPERS_H + +/* This file redefines API functions to be called through a wrapper macro, but +only for ports that are using the MPU. */ +#ifdef portUSING_MPU_WRAPPERS + + /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is + included from queue.c or task.c to prevent it from having an effect within + those files. */ + #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + + /* + * Map standard (non MPU) API functions to equivalents that start + * "MPU_". This will cause the application code to call the MPU_ + * version, which wraps the non-MPU version with privilege promoting + * then demoting code, so the kernel code always runs will full + * privileges. + */ + + /* Map standard tasks.h API functions to the MPU equivalents. */ + #define xTaskCreate MPU_xTaskCreate + #define xTaskCreateStatic MPU_xTaskCreateStatic + #define xTaskCreateRestricted MPU_xTaskCreateRestricted + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define vTaskDelete MPU_vTaskDelete + #define vTaskDelay MPU_vTaskDelay + #define vTaskDelayUntil MPU_vTaskDelayUntil + #define xTaskAbortDelay MPU_xTaskAbortDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define eTaskGetState MPU_eTaskGetState + #define vTaskGetInfo MPU_vTaskGetInfo + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define vTaskSuspend MPU_vTaskSuspend + #define vTaskResume MPU_vTaskResume + #define vTaskSuspendAll MPU_vTaskSuspendAll + #define xTaskResumeAll MPU_xTaskResumeAll + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define pcTaskGetName MPU_pcTaskGetName + #define xTaskGetHandle MPU_xTaskGetHandle + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer + #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle + #define uxTaskGetSystemState MPU_uxTaskGetSystemState + #define vTaskList MPU_vTaskList + #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats + #define xTaskGenericNotify MPU_xTaskGenericNotify + #define xTaskNotifyWait MPU_xTaskNotifyWait + #define ulTaskNotifyTake MPU_ulTaskNotifyTake + #define xTaskNotifyStateClear MPU_xTaskNotifyStateClear + + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState + #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + + /* Map standard queue.h API functions to the MPU equivalents. */ + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueGenericReceive MPU_xQueueGenericReceive + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable + #define vQueueDelete MPU_vQueueDelete + #define xQueueCreateMutex MPU_xQueueCreateMutex + #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic + #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore + #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic + #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueGenericCreate MPU_xQueueGenericCreate + #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic + #define xQueueCreateSet MPU_xQueueCreateSet + #define xQueueAddToSet MPU_xQueueAddToSet + #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet + #define xQueueSelectFromSet MPU_xQueueSelectFromSet + #define xQueueGenericReset MPU_xQueueGenericReset + + #if( configQUEUE_REGISTRY_SIZE > 0 ) + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #define pcQueueGetName MPU_pcQueueGetName + #endif + + /* Map standard timer.h API functions to the MPU equivalents. */ + #define xTimerCreate MPU_xTimerCreate + #define xTimerCreateStatic MPU_xTimerCreateStatic + #define pvTimerGetTimerID MPU_pvTimerGetTimerID + #define vTimerSetTimerID MPU_vTimerSetTimerID + #define xTimerIsTimerActive MPU_xTimerIsTimerActive + #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle + #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall + #define pcTimerGetName MPU_pcTimerGetName + #define xTimerGetPeriod MPU_xTimerGetPeriod + #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime + #define xTimerGenericCommand MPU_xTimerGenericCommand + + /* Map standard event_group.h API functions to the MPU equivalents. */ + #define xEventGroupCreate MPU_xEventGroupCreate + #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic + #define xEventGroupWaitBits MPU_xEventGroupWaitBits + #define xEventGroupClearBits MPU_xEventGroupClearBits + #define xEventGroupSetBits MPU_xEventGroupSetBits + #define xEventGroupSync MPU_xEventGroupSync + #define vEventGroupDelete MPU_vEventGroupDelete + + /* Remove the privileged function macro. */ + #define PRIVILEGED_FUNCTION + + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + + /* Ensure API functions go in the privileged execution section. */ + #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) + + #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +#else /* portUSING_MPU_WRAPPERS */ + + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA + #define portUSING_MPU_WRAPPERS 0 + +#endif /* portUSING_MPU_WRAPPERS */ + + +#endif /* MPU_WRAPPERS_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/port.c b/STM32F1/libraries/FreeRTOS900/utility/port.c new file mode 100644 index 0000000..6cfebe8 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/port.c @@ -0,0 +1,717 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is +defined. The value should also ensure backward compatibility. +FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0xFFUL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000UL ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* For strict compliance with the Cortex-M spec the task start address should +have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) + +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case it messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__ (( naked )); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvPortStartFirstTask( void ) __attribute__ (( naked )); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +// !!! Maple +//void vPortSVCHandler( void ) +void __exc_svc( void ) +// !!! Maple +{ + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " orr r14, #0xd \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +static void prvPortStartFirstTask( void ) +{ + __asm volatile( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); + + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + //vPortSetupTimerInterrupt(); + systick_attach_callback(&xPortSysTickHandler); + // !!! Maple + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + prvPortStartFirstTask(); + + /* Should never get here as the tasks will now be executing! Call the task + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ + prvTaskExitError(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + + // !!! Maple + //void xPortPendSVHandler( void ) + void __exc_pendsv( void ) + { + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n" /* Restore the context, including the critical nesting count. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ + " msr psp, r0 \n" + " isb \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + portDISABLE_INTERRUPTS(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portENABLE_INTERRUPTS(); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __asm volatile( "cpsid i" ); + __asm volatile( "dsb" ); + __asm volatile( "isb" ); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile( "dsb" ); + __asm volatile( "wfi" ); + __asm volatile( "isb" ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + + + + + + + + + + + + + + + + + + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/portable.h b/STM32F1/libraries/FreeRTOS900/utility/portable.h new file mode 100644 index 0000000..b9f8be3 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/portable.h @@ -0,0 +1,207 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. +Purely for reasons of backward compatibility the old method is still valid, but +to make it clear that new projects should not use it, support for the port +specific constants has been moved into the deprecated_definitions.h header +file. */ +#include "deprecated_definitions.h" + +/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h +did not result in a portmacro.h header file being included - and it should be +included here. In this case the path to the correct portmacro.h header file +must be set in the compiler's include path. */ +#ifndef portENTER_CRITICAL + #include "portmacro.h" +#endif + +#if portBYTE_ALIGNMENT == 32 + #define portBYTE_ALIGNMENT_MASK ( 0x001f ) +#endif + +#if portBYTE_ALIGNMENT == 16 + #define portBYTE_ALIGNMENT_MASK ( 0x000f ) +#endif + +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#ifndef portNUM_CONFIGURABLE_REGIONS + #define portNUM_CONFIGURABLE_REGIONS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpu_wrappers.h" + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; +#else + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; +#endif + +/* Used by heap_5.c. */ +typedef struct HeapRegion +{ + uint8_t *pucStartAddress; + size_t xSizeInBytes; +} HeapRegion_t; + +/* + * Used to define multiple heap regions for use by heap_5.c. This function + * must be called before any calls to pvPortMalloc() - not creating a task, + * queue, semaphore, mutex, software timer, event group, etc. will result in + * pvPortMalloc being called. + * + * pxHeapRegions passes in an array of HeapRegion_t structures - each of which + * defines a region of memory that can be used as the heap. The array is + * terminated by a HeapRegions_t structure that has a size of 0. The region + * with the lowest start address must appear first in the array. + */ +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; + + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void vPortFree( void *pv ) PRIVILEGED_FUNCTION; +void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; +size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; +size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/portmacro.h b/STM32F1/libraries/FreeRTOS900/utility/portmacro.h new file mode 100644 index 0000000..d44fc92 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/portmacro.h @@ -0,0 +1,284 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL + + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + not need to be guarded with a critical section. */ + #define portTICK_TYPE_IS_ATOMIC 1 +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +#define portYIELD() \ +{ \ + /* Set a PendSV to request a context switch. */ \ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ + \ + /* Barriers are normally not required but do ensure the code is completely \ + within the specified behaviour for the architecture. */ \ + __asm volatile( "dsb" ); \ + __asm volatile( "isb" ); \ +} + +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD() +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) +#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() +#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); + return ucReturn; + } + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#define portINLINE __inline + +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__(( always_inline)) +#endif + +portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) +{ +uint32_t ulCurrentInterrupt; +BaseType_t xReturn; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} + +/*-----------------------------------------------------------*/ + +portFORCE_INLINE static void vPortRaiseBASEPRI( void ) +{ +uint32_t ulNewBASEPRI; + + __asm volatile + ( + " mov %0, %1 \n" \ + " msr basepri, %0 \n" \ + " isb \n" \ + " dsb \n" \ + :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); +} + +/*-----------------------------------------------------------*/ + +portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) +{ +uint32_t ulOriginalBASEPRI, ulNewBASEPRI; + + __asm volatile + ( + " mrs %0, basepri \n" \ + " mov %1, %2 \n" \ + " msr basepri, %1 \n" \ + " isb \n" \ + " dsb \n" \ + :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); + + /* This return will not be reached but is necessary to prevent compiler + warnings. */ + return ulOriginalBASEPRI; +} +/*-----------------------------------------------------------*/ + +portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) +{ + __asm volatile + ( + " msr basepri, %0 " :: "r" ( ulNewMaskValue ) + ); +} +/*-----------------------------------------------------------*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/projdefs.h b/STM32F1/libraries/FreeRTOS900/utility/projdefs.h new file mode 100644 index 0000000..0b63fd8 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/projdefs.h @@ -0,0 +1,161 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* + * Defines the prototype to which task functions must conform. Defined in this + * file to ensure the type is known before portable.h is included. + */ +typedef void (*TaskFunction_t)( void * ); + +/* Converts a time in milliseconds to a time in ticks. This macro can be +overridden by a macro of the same name defined in FreeRTOSConfig.h in case the +definition here is not suitable for your application. */ +#ifndef pdMS_TO_TICKS + #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) ) +#endif + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) +#define errQUEUE_FULL ( ( BaseType_t ) 0 ) + +/* FreeRTOS error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +/* Macros used for basic data corruption checks. */ +#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES + #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 +#endif + +#if( configUSE_16_BIT_TICKS == 1 ) + #define pdINTEGRITY_CHECK_VALUE 0x5a5a +#else + #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL +#endif + +/* The following errno values are used by FreeRTOS+ components, not FreeRTOS +itself. */ +#define pdFREERTOS_ERRNO_NONE 0 /* No errors */ +#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ +#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ +#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */ +#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */ +#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */ +#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ +#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ +#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ +#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ +#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ +#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ +#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ +#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ +#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ +#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ +#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ +#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ +#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ +#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ +#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ +#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ +#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ +#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ +#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ +#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ +#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ +#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ +#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ +#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ +#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ +#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ +#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ +#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ +#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ +#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ +#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ +#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ +#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ + +/* The following endian values are used by FreeRTOS+ components, not FreeRTOS +itself. */ +#define pdFREERTOS_LITTLE_ENDIAN 0 +#define pdFREERTOS_BIG_ENDIAN 1 + +#endif /* PROJDEFS_H */ + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/queue.c b/STM32F1/libraries/FreeRTOS900/utility/queue.c new file mode 100644 index 0000000..ce623be --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/queue.c @@ -0,0 +1,2566 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#if ( configUSE_CO_ROUTINES == 1 ) + #include "croutine.h" +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* Constants used with the cRxLock and cTxLock structure members. */ +#define queueUNLOCKED ( ( int8_t ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) + +/* When the Queue_t structure is used to represent a base queue its pcHead and +pcTail members are used as pointers into the queue storage area. When the +Queue_t structure is used to represent a mutex pcHead and pcTail pointers are +not necessary, and the pcHead pointer is set to NULL to indicate that the +pcTail pointer actually points to the mutex holder (if any). Map alternative +names to the pcHead and pcTail structure members to ensure the readability of +the code is maintained despite this dual use of two structure members. An +alternative implementation would be to use a union, but use of a union is +against the coding standard (although an exception to the standard has been +permitted where the dual use also significantly changes the type of the +structure member). */ +#define pxMutexHolder pcTail +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL + +/* Semaphores do not actually store or copy data, so have an item size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define queueYIELD_IF_USING_PREEMPTION() +#else + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() +#endif + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. See the following link for the + * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html + */ +typedef struct QueueDefinition +{ + int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ + int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ + + union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ + { + int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + } u; + + List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ + UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ + + volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + struct QueueDefinition *pxQueueSetContainer; + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxQueueNumber; + uint8_t ucQueueType; + #endif + +} xQUEUE; + +/* The old xQUEUE name is maintained above then typedefed to the new Queue_t +name below to enable the use of older kernel aware debuggers. */ +typedef xQUEUE Queue_t; + +/*-----------------------------------------------------------*/ + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + QueueHandle_t xHandle; + } xQueueRegistryItem; + + /* The old xQueueRegistryItem name is maintained above then typedefed to the + new xQueueRegistryItem name below to enable the use of older kernel aware + debuggers. */ + typedef xQueueRegistryItem QueueRegistryItem_t; + + /* The queue registry is simply an array of QueueRegistryItem_t structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + +#endif /* configQUEUE_REGISTRY_SIZE */ + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +#if ( configUSE_QUEUE_SETS == 1 ) + /* + * Checks to see if a queue is a member of a queue set, and if so, notifies + * the queue set that the queue contains data. + */ + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +#endif + +/* + * Called after a Queue_t structure has been allocated either statically or + * dynamically to fill in the structure's members. + */ +static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; + +/* + * Mutexes are a special type of queue. When a mutex is created, first the + * queue is created, then prvInitialiseMutex() is called to configure the queue + * as a mutex. + */ +#if( configUSE_MUTEXES == 1 ) + static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; +#endif + +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL() +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) +{ +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize ); + pxQueue->cRxLock = queueUNLOCKED; + pxQueue->cTxLock = queueUNLOCKED; + + if( xNewQueue == pdFALSE ) + { + /* If there are tasks blocked waiting to read from the queue, then + the tasks will remain blocked as after this function exits the queue + will still be empty. If there are tasks blocked waiting to write to + the queue, then one should be unblocked as after this function exits + it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); + } + } + taskEXIT_CRITICAL(); + + /* A value is returned for calling semantic consistency with previous + versions. */ + return pdPASS; +} +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + + /* The StaticQueue_t structure and the queue storage area must be + supplied. */ + configASSERT( pxStaticQueue != NULL ); + + /* A queue storage area should be provided if the item size is not 0, and + should not be provided if the item size is 0. */ + configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); + configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); + + #if( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + variable of type StaticQueue_t or StaticSemaphore_t equals the size of + the real queue and semaphore structures. */ + volatile size_t xSize = sizeof( StaticQueue_t ); + configASSERT( xSize == sizeof( Queue_t ) ); + } + #endif /* configASSERT_DEFINED */ + + /* The address of a statically allocated queue was passed in, use it. + The address of a statically allocated storage area was also passed in + but is already set. */ + pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + + if( pxNewQueue != NULL ) + { + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Queues can be allocated wither statically or dynamically, so + note this queue was allocated statically in case the queue is + later deleted. */ + pxNewQueue->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + + return pxNewQueue; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + size_t xQueueSizeInBytes; + uint8_t *pucQueueStorage; + + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* There is not going to be a queue storage area. */ + xQueueSizeInBytes = ( size_t ) 0; + } + else + { + /* Allocate enough space to hold the maximum number of items that + can be in the queue at any time. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); + + if( pxNewQueue != NULL ) + { + /* Jump past the queue structure to find the location of the queue + storage area. */ + pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t ); + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Queues can be created either statically or dynamically, so + note this task was created dynamically in case it is later + deleted. */ + pxNewQueue->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + + return pxNewQueue; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) +{ + /* Remove compiler warnings about unused parameters should + configUSE_TRACE_FACILITY not be set to 1. */ + ( void ) ucQueueType; + + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* No RAM was allocated for the queue storage area, but PC head cannot + be set to NULL because NULL is used as a key to say the queue is used as + a mutex. Therefore just set pcHead to point to the queue as a benign + value that is known to be within the memory map. */ + pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; + } + else + { + /* Set the head to the start of the queue storage area. */ + pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; + } + + /* Initialise the queue members as described where the queue type is + defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ + + #if( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ + + traceQUEUE_CREATE( pxNewQueue ); +} +/*-----------------------------------------------------------*/ + +#if( configUSE_MUTEXES == 1 ) + + static void prvInitialiseMutex( Queue_t *pxNewQueue ) + { + if( pxNewQueue != NULL ) + { + /* The queue create function will set all the queue structure members + correctly for a generic queue, but this function is creating a + mutex. Overwrite those members that need to be set differently - + in particular the information required for priority inheritance. */ + pxNewQueue->pxMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* In case this is a recursive mutex. */ + pxNewQueue->u.uxRecursiveCallCount = 0; + + traceCREATE_MUTEX( pxNewQueue ); + + /* Start with the semaphore in the expected state. */ + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + + pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); + prvInitialiseMutex( pxNewQueue ); + + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) + { + Queue_t *pxNewQueue; + const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + + /* Prevent compiler warnings about unused parameters if + configUSE_TRACE_FACILITY does not equal 1. */ + ( void ) ucQueueType; + + pxNewQueue = ( Queue_t * ) xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); + prvInitialiseMutex( pxNewQueue ); + + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + + void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) + { + void *pxReturn; + + /* This function is called by xSemaphoreGetMutexHolder(), and should not + be called directly. Note: This is a good way of determining if the + calling task is the mutex holder, but not a good way of determining the + identity of the mutex holder, as the holder may change between the + following critical section exiting and the function returning. */ + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder; + } + else + { + pxReturn = NULL; + } + } + taskEXIT_CRITICAL(); + + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* If this is the task that holds the mutex then pxMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */ + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->u.uxRecursiveCallCount )--; + + /* Has the recursive call count unwound to 0? */ + if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + /* The mutex cannot be given because the calling task is not the + holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + { + ( pxMutex->u.uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); + + /* pdPASS will only be returned if the mutex was successfully + obtained. The calling task may have entered the Blocked state + before reaching here. */ + if( xReturn != pdFAIL ) + { + ( pxMutex->u.uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + return xHandle; + } + +#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + return xHandle; + } + +#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) +{ +BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? The running task must be the + highest priority task wanting to access the queue. If the head item + in the queue is to be overwritten then it does not matter if the + queue is full. */ + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND( pxQueue ); + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to + do this from within the critical section - the + kernel takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes + and the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes and + the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting + the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + /* Similar to xQueueGenericSend, except without blocking if there is no room + in the queue. Also don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + const int8_t cTxLock = pxQueue->cTxLock; + + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a + semaphore or mutex. That means prvCopyDataToQueue() cannot result + in a task disinheriting a priority and prvCopyDataToQueue() can be + called here even though the disinherit function does not check if + the scheduler is suspended before accessing the ready lists. */ + ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* Similar to xQueueGenericSendFromISR() but used with semaphores where the + item size is 0. Don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + + configASSERT( pxQueue ); + + /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() + if the item size is not 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); + + /* Normally a mutex would not be given from an interrupt, especially if + there is a mutex holder, as priority inheritance makes no sense for an + interrupts, only tasks. */ + configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* When the queue is used to implement a semaphore no data is ever + moved through the queue but it is still valid to see if the queue 'has + space'. */ + if( uxMessagesWaiting < pxQueue->uxLength ) + { + const int8_t cTxLock = pxQueue->cTxLock; + + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + /* A task can only have an inherited priority if it is a mutex + holder - and if there is a mutex holder then the mutex cannot be + given from an ISR. As this is the ISR version of the function it + can be assumed there is no mutex holder and no need to determine if + priority disinheritance is needed. Simply increase the count of + messages (semaphores) available. */ + pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1; + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) + { + /* The semaphore is a member of a queue set, and + posting to the queue set caused a higher priority + task to unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking ) +{ +BaseType_t xEntryTimeSet = pdFALSE; +TimeOut_t xTimeOut; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* Is there data in the queue now? To be running the calling task + must be the highest priority task wanting to access the queue. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember the read position in case the queue is only being + peeked. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Actually removing data, not just peeking. */ + pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1; + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* The data is not being removed, so reset the read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + taskENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* Cannot block in an ISR, so check there is data available. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + const int8_t cRxLock = pxQueue->cRxLock; + + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1; + + /* If the queue is locked the event list will not be modified. + Instead update the lock count so the task that unlocks the queue + will know that an ISR has removed data while the queue was + locked. */ + if( cRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_PEEK_FROM_ISR( pxQueue ); + + /* Remember the read position so it can be reset as nothing is + actually being removed from the queue. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; + + configASSERT( xQueue ); + + taskENTER_CRITICAL(); + { + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t *pxQueue; + + pxQueue = ( Queue_t * ) xQueue; + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; + + configASSERT( xQueue ); + + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +void vQueueDelete( QueueHandle_t xQueue ) +{ +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + traceQUEUE_DELETE( pxQueue ); + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueUnregisterQueue( pxQueue ); + } + #endif + + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The queue can only have been allocated dynamically - free it + again. */ + vPortFree( pxQueue ); + } + #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The queue could have been allocated statically or dynamically, so + check before attempting to free the memory. */ + if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxQueue ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else + { + /* The queue must have been statically allocated, so is not going to be + deleted. Avoid compiler warnings about the unused parameter. */ + ( void ) pxQueue; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) + { + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->ucQueueType; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) +{ +BaseType_t xReturn = pdFALSE; +UBaseType_t uxMessagesWaiting; + + /* This function is called from a critical section. */ + + uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + pxQueue->pxMutexHolder = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + } + else if( xPosition == queueSEND_TO_BACK ) + { + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */ + pxQueue->pcWriteTo += pxQueue->uxItemSize; + if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + pxQueue->u.pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xPosition == queueOVERWRITE ) + { + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* An item is not being added but overwritten, so subtract + one from the recorded number of items in the queue so when + one is added again below the number of recorded items remains + correct. */ + --uxMessagesWaiting; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) +{ + if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) + { + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( Queue_t * const pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(); + { + int8_t cTxLock = pxQueue->cTxLock; + + /* See if data was added to the queue while it was locked. */ + while( cTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting to + the queue set caused a higher priority task to unblock. + A context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Tasks that are removed from the event list will get + added to the pending ready list as the scheduler is still + suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that + a context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + #endif /* configUSE_QUEUE_SETS */ + + --cTxLock; + } + + pxQueue->cTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + int8_t cRxLock = pxQueue->cRxLock; + + while( cRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + --cRxLock; + } + else + { + break; + } + } + + pxQueue->cRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) +{ +BaseType_t xReturn; + + configASSERT( xQueue ); + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) +{ +BaseType_t xReturn; + + configASSERT( xQueue ); + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) + { + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCoRoutinePreviouslyWoken; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + + /* Note there is nothing here to protect against another task adding or + removing entries from the registry while it is being searched. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + pcReturn = xQueueRegistry[ ux ].pcQueueName; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return pcReturn; + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueUnregisterQueue( QueueHandle_t xQueue ) + { + UBaseType_t ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + + /* Set the handle to NULL to ensure the same queue handle cannot + appear in the registry twice if it is added, removed, then + added again. */ + xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TIMERS == 1 ) + + void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) + { + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements. + It can result in vListInsert() being called on a list that can only + possibly ever have one item in it, so the list will be fast, but even + so it should be called with the scheduler locked and not from a critical + section. */ + + /* Only do anything if there are no messages in the queue. This function + will not actually cause the task to block, just place it on a blocked + list. It will not block until the scheduler is unlocked - at which + time a yield will be performed. If an item is added to the queue while + the queue is locked, and the calling task blocks on the queue, then the + calling task will be immediately unblocked when the queue is unlocked. */ + prvLockQueue( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvUnlockQueue( pxQueue ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t pxQueue; + + pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); + + return pxQueue; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; + + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) + { + /* The queue was not a member of the set. */ + xReturn = pdFAIL; + } + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* It is dangerous to remove a queue from a set when the queue is + not empty because the queue set will still hold pending events for + the queue. */ + xReturn = pdFAIL; + } + else + { + taskENTER_CRITICAL(); + { + /* The queue is no longer contained in the set. */ + pxQueueOrSemaphore->pxQueueSetContainer = NULL; + } + taskEXIT_CRITICAL(); + xReturn = pdPASS; + } + + return xReturn; + } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) + { + Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; + BaseType_t xReturn = pdFALSE; + + /* This function must be called form a critical section. */ + + configASSERT( pxQueueSetContainer ); + configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); + + if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) + { + const int8_t cTxLock = pxQueueSetContainer->cTxLock; + + traceQUEUE_SEND( pxQueueSetContainer ); + + /* The data copied is the handle of the queue that contains data. */ + xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + + if( cTxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ + + + + + + + + + + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/queue.h b/STM32F1/libraries/FreeRTOS900/utility/queue.h new file mode 100644 index 0000000..30be360 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/queue.h @@ -0,0 +1,1798 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include queue.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Type by which queues are referenced. For example, a call to xQueueCreate() + * returns an QueueHandle_t variable that can then be used as a parameter to + * xQueueSend(), xQueueReceive(), etc. + */ +typedef void * QueueHandle_t; + +/** + * Type by which queue sets are referenced. For example, a call to + * xQueueCreateSet() returns an xQueueSet variable that can then be used as a + * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. + */ +typedef void * QueueSetHandle_t; + +/** + * Queue sets can contain both queues and semaphores, so the + * QueueSetMemberHandle_t is defined as a type to be used where a parameter or + * return value can be either an QueueHandle_t or an SemaphoreHandle_t. + */ +typedef void * QueueSetMemberHandle_t; + +/* For internal use only. */ +#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) +#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) +#define queueOVERWRITE ( ( BaseType_t ) 2 ) + +/* For internal use only. These definitions *must* match those in queue.c. */ +#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) + +/** + * queue. h + *
+ QueueHandle_t xQueueCreate(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize
+						  );
+ * 
+ * + * Creates a new queue instance, and returns a handle by which the new queue + * can be referenced. + * + * Internally, within the FreeRTOS implementation, queues use two blocks of + * memory. The first block is used to hold the queue's data structures. The + * second block is used to hold items placed into the queue. If a queue is + * created using xQueueCreate() then both blocks of memory are automatically + * dynamically allocated inside the xQueueCreate() function. (see + * http://www.freertos.org/a00111.html). If a queue is created using + * xQueueCreateStatic() then the application writer must provide the memory that + * will get used by the queue. xQueueCreateStatic() therefore allows a queue to + * be created without using any dynamic memory allocation. + * + * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+	if( xQueue1 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue2 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) +#endif + +/** + * queue. h + *
+ QueueHandle_t xQueueCreateStatic(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize,
+							  uint8_t *pucQueueStorageBuffer,
+							  StaticQueue_t *pxQueueBuffer
+						  );
+ * 
+ * + * Creates a new queue instance, and returns a handle by which the new queue + * can be referenced. + * + * Internally, within the FreeRTOS implementation, queues use two blocks of + * memory. The first block is used to hold the queue's data structures. The + * second block is used to hold items placed into the queue. If a queue is + * created using xQueueCreate() then both blocks of memory are automatically + * dynamically allocated inside the xQueueCreate() function. (see + * http://www.freertos.org/a00111.html). If a queue is created using + * xQueueCreateStatic() then the application writer must provide the memory that + * will get used by the queue. xQueueCreateStatic() therefore allows a queue to + * be created without using any dynamic memory allocation. + * + * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @param pucQueueStorageBuffer If uxItemSize is not zero then + * pucQueueStorageBuffer must point to a uint8_t array that is at least large + * enough to hold the maximum number of items that can be in the queue at any + * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is + * zero then pucQueueStorageBuffer can be NULL. + * + * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which + * will be used to hold the queue's data structure. + * + * @return If the queue is created then a handle to the created queue is + * returned. If pxQueueBuffer is NULL then NULL is returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+
+ // xQueueBuffer will hold the queue structure.
+ StaticQueue_t xQueueBuffer;
+
+ // ucQueueStorage will hold the items posted to the queue.  Must be at least
+ // [(queue length) * ( queue item size)] bytes long.
+ uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+							ITEM_SIZE	  // The size of each item in the queue
+							&( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+							&xQueueBuffer ); // The buffer that will hold the queue structure.
+
+	// The queue is guaranteed to be created successfully as no dynamic memory
+	// allocation is used.  Therefore xQueue1 is now a handle to a valid queue.
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreateStatic xQueueCreateStatic + * \ingroup QueueManagement + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * queue. h + *
+ BaseType_t xQueueSendToToFront(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ BaseType_t xQueueSendToBack(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueSend(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  TickType_t xTicksToWait
+						 );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwrite(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue
+						 );
+ * 
+ * + * Only for use with queues that have a length of one - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * This function must not be called from an interrupt service routine. + * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle of the queue to which the data is being sent. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and + * therefore has the same return values as xQueueSendToFront(). However, pdPASS + * is the only value that can be returned because xQueueOverwrite() will write + * to the queue even when the queue is already full. + * + * Example usage: +
+
+ void vFunction( void *pvParameters )
+ {
+ QueueHandle_t xQueue;
+ uint32_t ulVarToSend, ulValReceived;
+
+	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwrite() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+
+	// Write the value 10 to the queue using xQueueOverwrite().
+	ulVarToSend = 10;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// Peeking the queue should now return 10, but leave the value 10 in
+	// the queue.  A block time of zero is used as it is known that the
+	// queue holds a value.
+	ulValReceived = 0;
+	xQueuePeek( xQueue, &ulValReceived, 0 );
+
+	if( ulValReceived != 10 )
+	{
+		// Error unless the item was removed by a different task.
+	}
+
+	// The queue is still full.  Use xQueueOverwrite() to overwrite the
+	// value held in the queue with 100.
+	ulVarToSend = 100;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// This time read from the queue, leaving the queue empty once more.
+	// A block time of 0 is used again.
+	xQueueReceive( xQueue, &ulValReceived, 0 );
+
+	// The value read should be the last value written, even though the
+	// queue was already full when the value was written.
+	if( ulValReceived != 100 )
+	{
+		// Error!
+	}
+
+	// ...
+}
+ 
+ * \defgroup xQueueOverwrite xQueueOverwrite + * \ingroup QueueManagement + */ +#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericSend(
+									QueueHandle_t xQueue,
+									const void * pvItemToQueue,
+									TickType_t xTicksToWait
+									BaseType_t xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueuePeek(
+							 QueueHandle_t xQueue,
+							 void *pvBuffer,
+							 TickType_t xTicksToWait
+						 );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. See + * xQueuePeekFromISR() for an alternative that can be called from an interrupt + * service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Peek a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask, but the item still remains on the queue.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/** + * queue. h + *
+ BaseType_t xQueuePeekFromISR(
+									QueueHandle_t xQueue,
+									void *pvBuffer,
+								);
+ * + * A version of xQueuePeek() that can be called from an interrupt service + * routine (ISR). + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceive(
+								 QueueHandle_t xQueue,
+								 void *pvBuffer,
+								 TickType_t xTicksToWait
+							);
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_PERIOD_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericReceive(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   TickType_t	xTicksToWait
+									   BaseType_t	xJustPeek
+									);
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * + * Return the number of free spaces available in a queue. This is equal to the + * number of items that can be sent to the queue before the queue becomes full + * if no items are removed. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of spaces available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
void vQueueDelete( QueueHandle_t xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \defgroup vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueSendToFrontFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPrioritTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ BaseType_t xQueueSendToBackFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwriteFromISR(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  BaseType_t *pxHigherPriorityTaskWoken
+						 );
+ * 
+ * + * A version of xQueueOverwrite() that can be used in an interrupt service + * routine (ISR). + * + * Only for use with queues that can hold a single item - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return xQueueOverwriteFromISR() is a macro that calls + * xQueueGenericSendFromISR(), and therefore has the same return values as + * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be + * returned because xQueueOverwriteFromISR() will write to the queue even when + * the queue is already full. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ void vFunction( void *pvParameters )
+ {
+ 	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+}
+
+void vAnInterruptHandler( void )
+{
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+uint32_t ulVarToSend, ulValReceived;
+
+	// Write the value 10 to the queue using xQueueOverwriteFromISR().
+	ulVarToSend = 10;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// The queue is full, but calling xQueueOverwriteFromISR() again will still
+	// pass because the value held in the queue will be overwritten with the
+	// new value.
+	ulVarToSend = 100;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// Reading from the queue will now return 100.
+
+	// ...
+
+	if( xHigherPrioritytaskWoken == pdTRUE )
+	{
+		// Writing to the queue caused a task to unblock and the unblocked task
+		// has a priority higher than or equal to the priority of the currently
+		// executing task (the task this interrupt interrupted).  Perform a context
+		// switch so this interrupt returns directly to the unblocked task.
+		portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+	}
+}
+ 
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR + * \ingroup QueueManagement + */ +#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) + +/** + * queue. h + *
+ BaseType_t xQueueSendFromISR(
+									 QueueHandle_t xQueue,
+									 const void *pvItemToQueue,
+									 BaseType_t *pxHigherPriorityTaskWoken
+								);
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		// Actual macro used here is port specific.
+		portYIELD_FROM_ISR ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueGenericSendFromISR(
+										   QueueHandle_t		xQueue,
+										   const	void	*pvItemToQueue,
+										   BaseType_t	*pxHigherPriorityTaskWoken,
+										   BaseType_t	xCopyPosition
+									   );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. xQueueGiveFromISR() is an + * equivalent for use by semaphores that don't actually copy any data. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWokenByPost;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWokenByPost = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post each byte.
+		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.  Note that the
+	// name of the yield function required is port specific.
+	if( xHigherPriorityTaskWokenByPost )
+	{
+		taskYIELD_YIELD_FROM_ISR();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceiveFromISR(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   BaseType_t *pxTaskWoken
+								   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const TickType_t xTicksToWait = ( TickType_t )0xff;
+
+	// Create a queue capable of containing 10 characters.
+	xQueue = xQueueCreate( 10, sizeof( char ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Post some characters that will be used within an ISR.  If the queue
+	// is full then this task will block for xTicksToWait ticks.
+	cValueToPost = 'a';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+	cValueToPost = 'b';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+
+	// ... keep posting characters ... this task may block when the queue
+	// becomes full.
+
+	cValueToPost = 'c';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ BaseType_t xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+	{
+		// A character was received.  Output the character now.
+		vOutputCharacter( cRxedChar );
+
+		// If removing the character from the queue woke the task that was
+		// posting onto the queue cTaskWokenByReceive will have been set to
+		// pdTRUE.  No matter how many times this loop iterates only one
+		// task will be woken.
+	}
+
+	if( cTaskWokenByPost != ( char ) pdFALSE;
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + +/* + * Utilities to query queues that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ); +BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken ); +BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ); +BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ); + +/* + * For internal use only. Use xSemaphoreCreateMutex(), + * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling + * these functions directly. + */ +QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; +void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION; + +/* + * Reset a queue back to its original empty state. The return value is now + * obsolete and is always set to pdPASS. + */ +#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. The queue registry only + * stores a pointer to the string - so the string must be persistent (global or + * preferably in ROM/Flash), not on the stack. + */ +#if( configQUEUE_REGISTRY_SIZE > 0 ) + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to + * remove the queue, semaphore or mutex from the register. If you are not using + * a kernel aware debugger then this function can be ignored. + * + * @param xQueue The handle of the queue being removed from the registry. + */ +#if( configQUEUE_REGISTRY_SIZE > 0 ) + void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#endif + +/* + * The queue registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call pcQueueGetName() to look + * up and return the name of a queue in the queue registry from the queue's + * handle. + * + * @param xQueue The handle of the queue the name of which will be returned. + * @return If the queue is in the registry then a pointer to the name of the + * queue is returned. If the queue is not in the registry then NULL is + * returned. + */ +#if( configQUEUE_REGISTRY_SIZE > 0 ) + const char *pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/* + * Generic version of the function used to creaet a queue using dynamic memory + * allocation. This is called by other functions and macros that create other + * RTOS objects that use the queue structure as their base. + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +#endif + +/* + * Generic version of the function used to creaet a queue using dynamic memory + * allocation. This is called by other functions and macros that create other + * RTOS objects that use the queue structure as their base. + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +#endif + +/* + * Queue sets provide a mechanism to allow a task to block (pend) on a read + * operation from multiple queues or semaphores simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * A queue set must be explicitly created using a call to xQueueCreateSet() + * before it can be used. Once created, standard FreeRTOS queues and semaphores + * can be added to the set using calls to xQueueAddToSet(). + * xQueueSelectFromSet() is then used to determine which, if any, of the queues + * or semaphores contained in the set is in a state where a queue read or + * semaphore take operation would be successful. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: An additional 4 bytes of RAM is required for each space in a every + * queue added to a queue set. Therefore counting semaphores that have a high + * maximum count value should not be added to a queue set. + * + * Note 4: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param uxEventQueueLength Queue sets store events that occur on + * the queues and semaphores contained in the set. uxEventQueueLength specifies + * the maximum number of events that can be queued at once. To be absolutely + * certain that events are not lost uxEventQueueLength should be set to the + * total sum of the length of the queues added to the set, where binary + * semaphores and mutexes have a length of 1, and counting semaphores have a + * length set by their maximum count value. Examples: + * + If a queue set is to hold a queue of length 5, another queue of length 12, + * and a binary semaphore, then uxEventQueueLength should be set to + * (5 + 12 + 1), or 18. + * + If a queue set is to hold three binary semaphores then uxEventQueueLength + * should be set to (1 + 1 + 1 ), or 3. + * + If a queue set is to hold a counting semaphore that has a maximum count of + * 5, and a counting semaphore that has a maximum count of 3, then + * uxEventQueueLength should be set to (5 + 3), or 8. + * + * @return If the queue set is created successfully then a handle to the created + * queue set is returned. Otherwise NULL is returned. + */ +QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; + +/* + * Adds a queue or semaphore to a queue set that was previously created by a + * call to xQueueCreateSet(). + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being added to + * the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set to which the queue or semaphore + * is being added. + * + * @return If the queue or semaphore was successfully added to the queue set + * then pdPASS is returned. If the queue could not be successfully added to the + * queue set because it is already a member of a different queue set then pdFAIL + * is returned. + */ +BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * Removes a queue or semaphore from a queue set. A queue or semaphore can only + * be removed from a set if the queue or semaphore is empty. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being removed + * from the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set in which the queue or semaphore + * is included. + * + * @return If the queue or semaphore was successfully removed from the queue set + * then pdPASS is returned. If the queue was not in the queue set, or the + * queue (or semaphore) was not empty, then pdFAIL is returned. + */ +BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * xQueueSelectFromSet() selects from the members of a queue set a queue or + * semaphore that either contains data (in the case of a queue) or is available + * to take (in the case of a semaphore). xQueueSelectFromSet() effectively + * allows a task to block (pend) on a read operation on all the queues and + * semaphores in a queue set simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueSet The queue set on which the task will (potentially) block. + * + * @param xTicksToWait The maximum time, in ticks, that the calling task will + * remain in the Blocked state (with other tasks executing) to wait for a member + * of the queue set to be ready for a successful queue read or semaphore take + * operation. + * + * @return xQueueSelectFromSet() will return the handle of a queue (cast to + * a QueueSetMemberHandle_t type) contained in the queue set that contains data, + * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained + * in the queue set that is available, or NULL if no such queue or semaphore + * exists before before the specified block time expires. + */ +QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * A version of xQueueSelectFromSet() that can be used from an ISR. + */ +QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* Not public API functions. */ +void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; +void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + diff --git a/STM32F1/libraries/FreeRTOS900/utility/readme.txt b/STM32F1/libraries/FreeRTOS900/utility/readme.txt new file mode 100644 index 0000000..58480c5 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/readme.txt @@ -0,0 +1,17 @@ +Each real time kernel port consists of three files that contain the core kernel +components and are common to every port, and one or more files that are +specific to a particular microcontroller and or compiler. + ++ The FreeRTOS/Source directory contains the three files that are common to +every port - list.c, queue.c and tasks.c. The kernel is contained within these +three files. croutine.c implements the optional co-routine functionality - which +is normally only used on very memory limited systems. + ++ The FreeRTOS/Source/Portable directory contains the files that are specific to +a particular microcontroller and or compiler. + ++ The FreeRTOS/Source/include directory contains the real time kernel header +files. + +See the readme file in the FreeRTOS/Source/Portable directory for more +information. \ No newline at end of file diff --git a/STM32F1/libraries/FreeRTOS900/utility/semphr.h b/STM32F1/libraries/FreeRTOS900/utility/semphr.h new file mode 100644 index 0000000..a674b02 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/semphr.h @@ -0,0 +1,1171 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include semphr.h" +#endif + +#include "queue.h" + +typedef QueueHandle_t SemaphoreHandle_t; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) +#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
+ * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateBinary( void )
+ * + * Creates a new binary semaphore instance, and returns a handle by which the + * new semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, binary semaphores use a block + * of memory, in which the semaphore structure is stored. If a binary semaphore + * is created using xSemaphoreCreateBinary() then the required memory is + * automatically dynamically allocated inside the xSemaphoreCreateBinary() + * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * is created using xSemaphoreCreateBinaryStatic() then the application writer + * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a + * binary semaphore to be created without using any dynamic memory allocation. + * + * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @return Handle to the created semaphore, or NULL if the memory required to + * hold the semaphore's data structures could not be allocated. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
+ * + * Creates a new binary semaphore instance, and returns a handle by which the + * new semaphore can be referenced. + * + * NOTE: In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, binary semaphores use a block + * of memory, in which the semaphore structure is stored. If a binary semaphore + * is created using xSemaphoreCreateBinary() then the required memory is + * automatically dynamically allocated inside the xSemaphoreCreateBinary() + * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * is created using xSemaphoreCreateBinaryStatic() then the application writer + * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a + * binary semaphore to be created without using any dynamic memory allocation. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the semaphore's data structure, removing the + * need for the memory to be allocated dynamically. + * + * @return If the semaphore is created then a handle to the created semaphore is + * returned. If pxSemaphoreBuffer is NULL then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+    // The semaphore's data structures will be placed in the xSemaphoreBuffer
+    // variable, the address of which is passed into the function.  The
+    // function's parameter is not NULL, so the function will not attempt any
+    // dynamic memory allocation, and therefore the function will not return
+    // return NULL.
+    xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
+
+    // Rest of task code goes here.
+ }
+ 
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic + * \ingroup Semaphores + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * semphr. h + *
xSemaphoreTake(
+ *                   SemaphoreHandle_t xSemaphore,
+ *                   TickType_t xBlockTime
+ *               )
+ * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    xSemaphore = xSemaphoreCreateBinary();
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * SemaphoreHandle_t xMutex, + * TickType_t xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#if( configUSE_RECURSIVE_MUTEXES == 1 ) + #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) +#endif + +/** + * semphr. h + *
xSemaphoreGive( SemaphoreHandle_t xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    xSemaphore = vSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#if( configUSE_RECURSIVE_MUTEXES == 1 ) + #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) +#endif + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static uint8_t ucLocalTickCount = 0;
+ static BaseType_t xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
+ xSemaphoreTakeFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to take a semaphore from an ISR. The semaphore must have + * previously been created with a call to xSemaphoreCreateBinary() or + * xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR, however taking a semaphore from an ISR + * is not a common operation. It is likely to only be useful when taking a + * counting semaphore when an interrupt is obtaining an object from a resource + * pool (when the semaphore count indicates the number of resources available). + * + * @param xSemaphore A handle to the semaphore being taken. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully taken, otherwise + * pdFALSE + */ +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateMutex( void )
+ * + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, mutex semaphores use a block + * of memory, in which the mutex structure is stored. If a mutex is created + * using xSemaphoreCreateMutex() then the required memory is automatically + * dynamically allocated inside the xSemaphoreCreateMutex() function. (see + * http://www.freertos.org/a00111.html). If a mutex is created using + * xSemaphoreCreateMutexStatic() then the application writer must provided the + * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created + * without using any dynamic memory allocation. + * + * Mutexes created using this function can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros must not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return If the mutex was successfully created then a handle to the created + * semaphore is returned. If there was not enough heap to allocate the mutex + * data structures then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ * + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, mutex semaphores use a block + * of memory, in which the mutex structure is stored. If a mutex is created + * using xSemaphoreCreateMutex() then the required memory is automatically + * dynamically allocated inside the xSemaphoreCreateMutex() function. (see + * http://www.freertos.org/a00111.html). If a mutex is created using + * xSemaphoreCreateMutexStatic() then the application writer must provided the + * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created + * without using any dynamic memory allocation. + * + * Mutexes created using this function can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros must not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, + * which will be used to hold the mutex's data structure, removing the need for + * the memory to be allocated dynamically. + * + * @return If the mutex was successfully created then a handle to the created + * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // A mutex cannot be used before it has been created.  xMutexBuffer is
+    // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
+    // attempted.
+    xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
+
+    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+    // so there is no need to check it.
+ }
+ 
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic + * \ingroup Semaphores + */ + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
+ * + * Creates a new recursive mutex type semaphore instance, and returns a handle + * by which the new recursive mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * of memory, in which the mutex structure is stored. If a recursive mutex is + * created using xSemaphoreCreateRecursiveMutex() then the required memory is + * automatically dynamically allocated inside the + * xSemaphoreCreateRecursiveMutex() function. (see + * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * xSemaphoreCreateRecursiveMutexStatic() then the application writer must + * provide the memory that will get used by the mutex. + * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to + * be created without using any dynamic memory allocation. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros must not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex + * \ingroup Semaphores + */ +#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) + #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ * + * Creates a new recursive mutex type semaphore instance, and returns a handle + * by which the new recursive mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * of memory, in which the mutex structure is stored. If a recursive mutex is + * created using xSemaphoreCreateRecursiveMutex() then the required memory is + * automatically dynamically allocated inside the + * xSemaphoreCreateRecursiveMutex() function. (see + * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * xSemaphoreCreateRecursiveMutexStatic() then the application writer must + * provide the memory that will get used by the mutex. + * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to + * be created without using any dynamic memory allocation. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros must not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the recursive mutex's data structure, + * removing the need for the memory to be allocated dynamically. + * + * @return If the recursive mutex was successfully created then a handle to the + * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is + * returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // A recursive semaphore cannot be used before it is created.  Here a
+    // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
+    // The address of xMutexBuffer is passed into the function, and will hold
+    // the mutexes data structures - so no dynamic memory allocation will be
+    // attempted.
+    xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
+
+    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+    // so there is no need to check it.
+ }
+ 
+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic + * \ingroup Semaphores + */ +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) + #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
+ * + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer can + * instead optionally provide the memory that will get used by the counting + * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting + * semaphore to be created without using any dynamic memory allocation. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )
+ * + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer must + * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a + * counting semaphore to be created without using any dynamic memory allocation. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the semaphore's data structure, removing the + * need for the memory to be allocated dynamically. + * + * @return If the counting semaphore was successfully created then a handle to + * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL + * then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Counting semaphore cannot be used before they have been created.  Create
+    // a counting semaphore using xSemaphoreCreateCountingStatic().  The max
+    // value to which the semaphore can count is 10, and the initial value
+    // assigned to the count will be 0.  The address of xSemaphoreBuffer is
+    // passed in and will be used to hold the semaphore structure, so no dynamic
+    // memory allocation will be used.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
+
+    // No memory allocation was attempted so xSemaphore cannot be NULL, so there
+    // is no need to check its value.
+ }
+ 
+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic + * \ingroup Semaphores + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * semphr. h + *
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
+ * + * Delete a semaphore. This function must be used with care. For example, + * do not delete a mutex type semaphore if the mutex is held by a task. + * + * @param xSemaphore A handle to the semaphore to be deleted. + * + * \defgroup vSemaphoreDelete vSemaphoreDelete + * \ingroup Semaphores + */ +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) + +/** + * semphr.h + *
TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
+ * + * If xMutex is indeed a mutex type semaphore, return the current mutex holder. + * If xMutex is not a mutex type semaphore, or the mutex is available (not held + * by a task), return NULL. + * + * Note: This is a good way of determining if the calling task is the mutex + * holder, but not a good way of determining the identity of the mutex holder as + * the holder may change between the function exiting and the returned value + * being tested. + */ +#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) + +/** + * semphr.h + *
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
+ * + * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns + * its current count value. If the semaphore is a binary semaphore then + * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the + * semaphore is not available. + * + */ +#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) + +#endif /* SEMAPHORE_H */ + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/stdint.readme b/STM32F1/libraries/FreeRTOS900/utility/stdint.readme new file mode 100644 index 0000000..4414c29 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/stdint.readme @@ -0,0 +1,27 @@ + +#ifndef FREERTOS_STDINT +#define FREERTOS_STDINT + +/******************************************************************************* + * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions + * necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be + * built using compilers that do not provide their own stdint.h definition. + * + * To use this file: + * + * 1) Copy this file into the directory that contains your FreeRTOSConfig.h + * header file, as that directory will already be in the compilers include + * path. + * + * 2) Rename the copied file stdint.h. + * + */ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; + +#endif /* FREERTOS_STDINT */ diff --git a/STM32F1/libraries/FreeRTOS900/utility/task.h b/STM32F1/libraries/FreeRTOS900/utility/task.h new file mode 100644 index 0000000..d0643c0 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/task.h @@ -0,0 +1,2267 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef INC_TASK_H +#define INC_TASK_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include task.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V9.0.0" +#define tskKERNEL_VERSION_MAJOR 9 +#define tskKERNEL_VERSION_MINOR 0 +#define tskKERNEL_VERSION_BUILD 0 + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an TaskHandle_t variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \defgroup TaskHandle_t TaskHandle_t + * \ingroup Tasks + */ +typedef void * TaskHandle_t; + +/* + * Defines the prototype to which the application task hook function must + * conform. + */ +typedef BaseType_t (*TaskHookFunction_t)( void * ); + +/* Task states returned by eTaskGetState. */ +typedef enum +{ + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a read or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ + eInvalid /* Used as an 'invalid state' value. */ +} eTaskState; + +/* Actions that can be performed when vTaskNotify() is called. */ +typedef enum +{ + eNoAction = 0, /* Notify the task without updating its notify value. */ + eSetBits, /* Set bits in the task's notification value. */ + eIncrement, /* Increment the task's notification value. */ + eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ + eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ +} eNotifyAction; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT +{ + BaseType_t xOverflowCount; + TickType_t xTimeOnEntering; +} TimeOut_t; + +/* + * Defines the memory ranges allocated to the task when an MPU is used. + */ +typedef struct xMEMORY_REGION +{ + void *pvBaseAddress; + uint32_t ulLengthInBytes; + uint32_t ulParameters; +} MemoryRegion_t; + +/* + * Parameters required to create an MPU protected task. + */ +typedef struct xTASK_PARAMETERS +{ + TaskFunction_t pvTaskCode; + const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + uint16_t usStackDepth; + void *pvParameters; + UBaseType_t uxPriority; + StackType_t *puxStackBuffer; + MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} TaskParameters_t; + +/* Used with the uxTaskGetSystemState() function to return the state of each task +in the system. */ +typedef struct xTASK_STATUS +{ + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */ + uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ +} TaskStatus_t; + +/* Possible return values for eTaskConfirmSleepModeStatus(). */ +typedef enum +{ + eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ + eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ +} eSleepModeStatus; + +/** + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \defgroup taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL() portENTER_CRITICAL() +#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() +#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is +0 to generate more optimal code when configASSERT() is defined as the constant +is used in assert() statements. */ +#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) +#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) +#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) + + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ BaseType_t xTaskCreate(
+							  TaskFunction_t pvTaskCode,
+							  const char * const pcName,
+							  uint16_t usStackDepth,
+							  void *pvParameters,
+							  UBaseType_t uxPriority,
+							  TaskHandle_t *pvCreatedTask
+						  );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * Internally, within the FreeRTOS implementation, tasks use two blocks of + * memory. The first block is used to hold the task's data structures. The + * second block is used by the task as its stack. If a task is created using + * xTaskCreate() then both blocks of memory are automatically dynamically + * allocated inside the xTaskCreate() function. (see + * http://www.freertos.org/a00111.html). If a task is created using + * xTaskCreateStatic() then the application writer must provide the required + * memory. xTaskCreateStatic() therefore allows a task to be created without + * using any dynamic memory allocation. + * + * See xTaskCreateStatic() for a version that does not use any dynamic memory + * allocation. + * + * xTaskCreate() can only be used to create a task that has unrestricted + * access to the entire microcontroller memory map. Systems that include MPU + * support can alternatively create an MPU constrained task using + * xTaskCreateRestricted(). + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. Systems that + * include MPU support can optionally create tasks in a privileged (system) + * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For + * example, to create a privileged task at priority 2 the uxPriority parameter + * should be set to ( 2 | portPRIVILEGE_BIT ). + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+	 }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static uint8_t ucParameterToPass;
+ TaskHandle_t xHandle = NULL;
+
+	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+	 // the new task attempts to access it.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+     configASSERT( xHandle );
+
+	 // Use the handle to delete the task.
+     if( xHandle != NULL )
+     {
+	     vTaskDelete( xHandle );
+     }
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/** + * task. h + *
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
+								 const char * const pcName,
+								 uint32_t ulStackDepth,
+								 void *pvParameters,
+								 UBaseType_t uxPriority,
+								 StackType_t *pxStackBuffer,
+								 StaticTask_t *pxTaskBuffer );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * Internally, within the FreeRTOS implementation, tasks use two blocks of + * memory. The first block is used to hold the task's data structures. The + * second block is used by the task as its stack. If a task is created using + * xTaskCreate() then both blocks of memory are automatically dynamically + * allocated inside the xTaskCreate() function. (see + * http://www.freertos.org/a00111.html). If a task is created using + * xTaskCreateStatic() then the application writer must provide the required + * memory. xTaskCreateStatic() therefore allows a task to be created without + * using any dynamic memory allocation. + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. The maximum length of the string is defined by + * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. + * + * @param ulStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task will run. + * + * @param pxStackBuffer Must point to a StackType_t array that has at least + * ulStackDepth indexes - the array will then be used as the task's stack, + * removing the need for the stack to be allocated dynamically. + * + * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will + * then be used to hold the task's data structures, removing the need for the + * memory to be allocated dynamically. + * + * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will + * be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer + * are NULL then the task will not be created and + * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned. + * + * Example usage: +
+
+    // Dimensions the buffer that the task being created will use as its stack.
+    // NOTE:  This is the number of words the stack will hold, not the number of
+    // bytes.  For example, if each stack item is 32-bits, and this is set to 100,
+    // then 400 bytes (100 * 32-bits) will be allocated.
+    #define STACK_SIZE 200
+
+    // Structure that will hold the TCB of the task being created.
+    StaticTask_t xTaskBuffer;
+
+    // Buffer that the task being created will use as its stack.  Note this is
+    // an array of StackType_t variables.  The size of StackType_t is dependent on
+    // the RTOS port.
+    StackType_t xStack[ STACK_SIZE ];
+
+    // Function that implements the task being created.
+    void vTaskCode( void * pvParameters )
+    {
+        // The parameter value is expected to be 1 as 1 is passed in the
+        // pvParameters value in the call to xTaskCreateStatic().
+        configASSERT( ( uint32_t ) pvParameters == 1UL );
+
+        for( ;; )
+        {
+            // Task code goes here.
+        }
+    }
+
+    // Function that creates a task.
+    void vOtherFunction( void )
+    {
+        TaskHandle_t xHandle = NULL;
+
+        // Create the task without using any dynamic memory allocation.
+        xHandle = xTaskCreateStatic(
+                      vTaskCode,       // Function that implements the task.
+                      "NAME",          // Text name for the task.
+                      STACK_SIZE,      // Stack size in words, not bytes.
+                      ( void * ) 1,    // Parameter passed into the task.
+                      tskIDLE_PRIORITY,// Priority at which the task is created.
+                      xStack,          // Array to use as the task's stack.
+                      &xTaskBuffer );  // Variable to hold the task's data structure.
+
+        // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
+        // been created, and xHandle will be the task's handle.  Use the handle
+        // to suspend the task.
+        vTaskSuspend( xHandle );
+    }
+   
+ * \defgroup xTaskCreateStatic xTaskCreateStatic + * \ingroup Tasks + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * task. h + *
+ BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * + * xTaskCreateRestricted() should only be used in systems that include an MPU + * implementation. + * + * Create a new task and add it to the list of tasks that are ready to run. + * The function parameters define the memory regions and associated access + * permissions allocated to the task. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+// Create an TaskParameters_t structure that defines the task to be created.
+static const TaskParameters_t xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// and/or timer task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif + +/** + * task. h + *
+ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
+ * + * Memory regions are assigned to a restricted task when the task is created by + * a call to xTaskCreateRestricted(). These regions can be redefined using + * vTaskAllocateMPURegions(). + * + * @param xTask The handle of the task being updated. + * + * @param xRegions A pointer to an MemoryRegion_t structure that contains the + * new memory region definitions. + * + * Example usage: +
+// Define an array of MemoryRegion_t structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array.  The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{
+	// Base address		Length		Parameters
+	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+	{ 0,				0,			0 },
+	{ 0,				0,			0 }
+};
+
+void vATask( void *pvParameters )
+{
+	// This task was created such that it has access to certain regions of
+	// memory as defined by the MPU configuration.  At some point it is
+	// desired that these MPU regions are replaced with that defined in the
+	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+	// for this purpose.  NULL is used as the task handle to indicate that this
+	// function should modify the MPU regions of the calling task.
+	vTaskAllocateMPURegions( NULL, xAltRegions );
+
+	// Now the task can continue its function, but from this point on can only
+	// access its stack and the ucOneKByte array (unless any other statically
+	// defined or shared regions have been declared elsewhere).
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelete( TaskHandle_t xTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernel's management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param xTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create the task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( const TickType_t xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a periodic task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const TickType_t xDelay = 500 / portTICK_PERIOD_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by periodic + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ TickType_t xLastWakeTime;
+ const TickType_t xFrequency = 10;
+
+	 // Initialise the xLastWakeTime variable with the current time.
+	 xLastWakeTime = xTaskGetTickCount ();
+	 for( ;; )
+	 {
+		 // Wait for the next cycle.
+		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+		 // Perform action here.
+	 }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
+ * + * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this + * function to be available. + * + * A task will enter the Blocked state when it is waiting for an event. The + * event it is waiting for can be a temporal event (waiting for a time), such + * as when vTaskDelay() is called, or an event on an object, such as when + * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task + * that is in the Blocked state is used in a call to xTaskAbortDelay() then the + * task will leave the Blocked state, and return from whichever function call + * placed the task into the Blocked state. + * + * @param xTask The handle of the task to remove from the Blocked state. + * + * @return If the task referenced by xTask was not in the Blocked state then + * pdFAIL is returned. Otherwise pdPASS is returned. + * + * \defgroup xTaskAbortDelay xTaskAbortDelay + * \ingroup TaskCtrl + */ +BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param xTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of xTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to obtain the priority of the created task.
+	 // It was created with tskIDLE_PRIORITY, but may have changed
+	 // it itself.
+	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+	 {
+		 // The task has changed it's priority.
+	 }
+
+	 // ...
+
+	 // Is our priority higher than the created task?
+	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+	 {
+		 // Our priority (obtained using NULL handle) is higher.
+	 }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask );
+ * + * A version of uxTaskPriorityGet() that can be used from an ISR. + */ +UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
eTaskState eTaskGetState( TaskHandle_t xTask );
+ * + * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the state of any task. States are encoded by the eTaskState + * enumerated type. + * + * @param xTask Handle of the task to be queried. + * + * @return The state of xTask at the time the function was called. Note the + * state of the task might change between the function being called, and the + * functions return value being tested by the calling task. + */ +eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
+ * + * configUSE_TRACE_FACILITY must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * Populates a TaskStatus_t structure with information about a task. + * + * @param xTask Handle of the task being queried. If xTask is NULL then + * information will be returned about the calling task. + * + * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be + * filled with information about the task referenced by the handle passed using + * the xTask parameter. + * + * @xGetFreeStackSpace The TaskStatus_t structure contains a member to report + * the stack high water mark of the task being queried. Calculating the stack + * high water mark takes a relatively long time, and can make the system + * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to + * allow the high water mark checking to be skipped. The high watermark value + * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is + * not set to pdFALSE; + * + * @param eState The TaskStatus_t structure contains a member to report the + * state of the task being queried. Obtaining the task state is not as fast as + * a simple assignment - so the eState parameter is provided to allow the state + * information to be omitted from the TaskStatus_t structure. To obtain state + * information then set eState to eInvalid - otherwise the value passed in + * eState will be reported as the task state in the TaskStatus_t structure. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+ TaskStatus_t xTaskDetails;
+
+    // Obtain the handle of a task from its name.
+    xHandle = xTaskGetHandle( "Task_Name" );
+
+    // Check the handle is not NULL.
+    configASSERT( xHandle );
+
+    // Use the handle to obtain further information about the task.
+    vTaskGetInfo( xHandle,
+                  &xTaskDetails,
+                  pdTRUE, // Include the high water mark in xTaskDetails.
+                  eInvalid ); // Include the task state in xTaskDetails.
+ }
+   
+ * \defgroup vTaskGetInfo vTaskGetInfo + * \ingroup TaskCtrl + */ +void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param xTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to raise the priority of the created task.
+	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+	 // ...
+
+	 // Use a NULL handle to raise our priority to the same value.
+	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Suspend ourselves.
+	 vTaskSuspend( NULL );
+
+	 // We cannot get here unless another task calls vTaskResume
+	 // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskResume( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param xTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Resume the suspended task ourselves.
+	 vTaskResume( xHandle );
+
+	 // The created task will once again get microcontroller processing
+	 // time in accordance with its priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * xTaskResumeFromISR() should not be used to synchronise a task with an + * interrupt if there is a chance that the interrupt could arrive prior to the + * task being suspended - as this can lead to interrupts being missed. Use of a + * semaphore as a synchronisation mechanism would avoid this eventuality. + * + * @param xTaskToResume Handle to the task being readied. + * + * @return pdTRUE if resuming the task should result in a context switch, + * otherwise pdFALSE. This is used by the ISR to determine if a context switch + * may be required following the ISR. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * NOTE: At the time of writing only the x86 real mode port, which runs on a PC + * in place of DOS, implements this function. + * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // At some point we want to end the real time kernel processing
+		 // so call ...
+		 vTaskEndScheduler ();
+	 }
+ }
+
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will only get here when the vTaskCode () task has called
+	 // vTaskEndScheduler ().  When we get here we are back to single task
+	 // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the kernel
+		 // tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.
+		 xTaskResumeAll ();
+	 }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskResumeAll( void );
+ * + * Resumes scheduler activity after it was suspended by a call to + * vTaskSuspendAll(). + * + * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks + * that were previously suspended by a call to vTaskSuspend(). + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the real
+		 // time kernel tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.  We want to force
+		 // a context switch - but there is no point if resuming the scheduler
+		 // caused a context switch already.
+		 if( !xTaskResumeAll () )
+		 {
+			  taskYIELD ();
+		 }
+	 }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
TickType_t xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \defgroup xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
TickType_t xTaskGetTickCountFromISR( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * This is a version of xTaskGetTickCount() that is safe to be called from an + * ISR - provided that TickType_t is the natural word size of the + * microcontroller being used or interrupt nesting is either not supported or + * not being used. + * + * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
uint16_t uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
char *pcTaskGetName( TaskHandle_t xTaskToQuery );
+ * + * @return The text (human readable) name of the task referenced by the handle + * xTaskToQuery. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. + * + * \defgroup pcTaskGetName pcTaskGetName + * \ingroup TaskUtils + */ +char *pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
+ * + * NOTE: This function takes a relatively long time to complete and should be + * used sparingly. + * + * @return The handle of the task that has the human readable name pcNameToQuery. + * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle + * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available. + * + * \defgroup pcTaskGetHandle pcTaskGetHandle + * \ingroup TaskUtils + */ +TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task.h + *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in words, so on a 32 bit machine + * a value of 1 means 4 bytes) since the task started. The smaller the returned + * number the closer the task has come to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in words, so + * actual spaces on the stack rather than bytes) since the task referenced by + * xTask was created. + */ +UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* When using trace macros it is sometimes necessary to include task.h before +FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, +so the following two prototypes will cause a compilation error. This can be +fixed by simply guarding against the inclusion of these two prototypes unless +they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration +constant. */ +#ifdef configUSE_APPLICATION_TASK_TAG + #if configUSE_APPLICATION_TASK_TAG == 1 + /** + * task.h + *
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; + + /** + * task.h + *
void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ + +#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + + /* Each task contains an array of pointers that is dimensioned by the + configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The + kernel does not use the pointers itself, so the application writer can use + the pointers for any purpose they wish. The following two functions are + used to set and query a pointer respectively. */ + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION; + void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; + +#endif + +/** + * task.h + *
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. The return value is the value returned by the task hook function + * registered by the user. + */ +BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION; + +/** + * xTaskGetIdleTaskHandle() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the idle task. It is not valid to call + * xTaskGetIdleTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; + +/** + * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for + * uxTaskGetSystemState() to be available. + * + * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in + * the system. TaskStatus_t structures contain, among other things, members + * for the task handle, task name, task priority, task state, and total amount + * of run time consumed by the task. See the TaskStatus_t structure + * definition in this file for the full member list. + * + * NOTE: This function is intended for debugging use only as its use results in + * the scheduler remaining suspended for an extended period. + * + * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. + * The array must contain at least one TaskStatus_t structure for each task + * that is under the control of the RTOS. The number of tasks under the control + * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. + * + * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray + * parameter. The size is specified as the number of indexes in the array, or + * the number of TaskStatus_t structures contained in the array, not by the + * number of bytes in the array. + * + * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in + * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the + * total run time (as defined by the run time stats clock, see + * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. + * pulTotalRunTime can be set to NULL to omit the total run time information. + * + * @return The number of TaskStatus_t structures that were populated by + * uxTaskGetSystemState(). This should equal the number returned by the + * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed + * in the uxArraySize parameter was too small. + * + * Example usage: +
+    // This example demonstrates how a human readable table of run time stats
+	// information is generated from raw data provided by uxTaskGetSystemState().
+	// The human readable table is written to pcWriteBuffer
+	void vTaskGetRunTimeStats( char *pcWriteBuffer )
+	{
+	TaskStatus_t *pxTaskStatusArray;
+	volatile UBaseType_t uxArraySize, x;
+	uint32_t ulTotalRunTime, ulStatsAsPercentage;
+
+		// Make sure the write buffer does not contain a string.
+		*pcWriteBuffer = 0x00;
+
+		// Take a snapshot of the number of tasks in case it changes while this
+		// function is executing.
+		uxArraySize = uxTaskGetNumberOfTasks();
+
+		// Allocate a TaskStatus_t structure for each task.  An array could be
+		// allocated statically at compile time.
+		pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
+
+		if( pxTaskStatusArray != NULL )
+		{
+			// Generate raw status information about each task.
+			uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+
+			// For percentage calculations.
+			ulTotalRunTime /= 100UL;
+
+			// Avoid divide by zero errors.
+			if( ulTotalRunTime > 0 )
+			{
+				// For each populated position in the pxTaskStatusArray array,
+				// format the raw data as human readable ASCII data
+				for( x = 0; x < uxArraySize; x++ )
+				{
+					// What percentage of the total run time has the task used?
+					// This will always be rounded down to the nearest integer.
+					// ulTotalRunTimeDiv100 has already been divided by 100.
+					ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+
+					if( ulStatsAsPercentage > 0UL )
+					{
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+					}
+					else
+					{
+						// If the percentage is zero here then the task has
+						// consumed less than 1% of the total run time.
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+					}
+
+					pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+				}
+			}
+
+			// The array is no longer needed, free the memory it consumes.
+			vPortFree( pxTaskStatusArray );
+		}
+	}
+	
+ */ +UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskList( char *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must + * both be defined as 1 for this function to be available. See the + * configuration section of the FreeRTOS.org website for more information. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays task + * names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that might + * bloat the code size, use a lot of stack, and provide different results on + * different platforms. An alternative, tiny, third party, and limited + * functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly through a + * call to vTaskList(). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ASCII form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \defgroup vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS + * must both be defined as 1 for this function to be available. The application + * must also then provide definitions for + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() + * to configure a peripheral timer/counter and return the timers current count + * value respectively. The counter should be at least 10 times the frequency of + * the tick count. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * NOTE 2: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays the + * amount of time each task has spent in the Running state in both absolute and + * percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function + * that might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, and + * limited functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() directly + * to get access to raw stats data, rather than indirectly through a call to + * vTaskGetRunTimeStats(). + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ASCII form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * pulPreviousNotificationValue - + * Can be used to pass out the subject task's notification value before any + * bits are modified by the notify function. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; +#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) +#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * A version of xTaskNotify() that can be used from an interrupt service routine + * (ISR). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the + * task to which the notification was sent to leave the Blocked state, and the + * unblocked task has a priority higher than the currently running task. If + * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should + * be requested before the interrupt is exited. How a context switch is + * requested from an ISR is dependent on the port - see the documentation page + * for the port in use. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value + * will be cleared in the calling task's notification value before the task + * checks to see if any notifications are pending, and optionally blocks if no + * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if + * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have + * the effect of resetting the task's notification value to 0. Setting + * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. + * + * @param ulBitsToClearOnExit If a notification is pending or received before + * the calling task exits the xTaskNotifyWait() function then the task's + * notification value (see the xTaskNotify() API function) is passed out using + * the pulNotificationValue parameter. Then any bits that are set in + * ulBitsToClearOnExit will be cleared in the task's notification value (note + * *pulNotificationValue is set before any bits are cleared). Setting + * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL + * (if limits.h is not included) will have the effect of resetting the task's + * notification value to 0 before the function exits. Setting + * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged + * when the function exits (in which case the value passed out in + * pulNotificationValue will match the task's notification value). + * + * @param pulNotificationValue Used to pass the task's notification value out + * of the function. Note the value passed out will not be effected by the + * clearing of any bits caused by ulBitsToClearOnExit being non-zero. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for a notification to be received, should a notification + * not already be pending when xTaskNotifyWait() was called. The task + * will not consume any processing time while it is in the Blocked state. This + * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be + * used to convert a time specified in milliseconds to a time specified in + * ticks. + * + * @return If a notification was received (including notifications that were + * already pending when xTaskNotifyWait was called) then pdPASS is + * returned. Otherwise pdFAIL is returned. + * + * \defgroup xTaskNotifyWait xTaskNotifyWait + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro + * to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * xTaskNotifyGive() is a helper macro intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. + * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, + * the equivalent action that instead uses a task notification is + * xTaskNotifyGive(). + * + * When task notifications are being used as a binary or counting semaphore + * equivalent then the task being notified should wait for the notification + * using the ulTaskNotificationTake() API function rather than the + * xTaskNotifyWait() API function. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the + * eAction parameter set to eIncrement - so pdPASS is always returned. + * + * \defgroup xTaskNotifyGive xTaskNotifyGive + * \ingroup TaskNotifications + */ +#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) + +/** + * task. h + *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
+ * to be available.
+ *
+ * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
+ * "notification value", which is a 32-bit unsigned integer (uint32_t).
+ *
+ * A version of xTaskNotifyGive() that can be called from an interrupt service
+ * routine (ISR).
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment the task's notification value.  In that way
+ * task notifications can be used to send data to a task, or be used as light
+ * weight and fast binary or counting semaphores.
+ *
+ * vTaskNotifyGiveFromISR() is intended for use when task notifications are
+ * used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given from an ISR using the
+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
+ * a task notification is vTaskNotifyGiveFromISR().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotificationTake() API function rather than the
+ * xTaskNotifyWait() API function.
+ *
+ * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param pxHigherPriorityTaskWoken  vTaskNotifyGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task.  If
+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
+ * should be requested before the interrupt is exited.  How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * \defgroup xTaskNotifyWait xTaskNotifyWait
+ * \ingroup TaskNotifications
+ */
+void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * 
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * ulTaskNotifyTake() is intended for use when a task notification is used as a + * faster and lighter weight binary or counting semaphore alternative. Actual + * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the + * equivalent action that instead uses a task notification is + * ulTaskNotifyTake(). + * + * When a task is using its notification value as a binary or counting semaphore + * other tasks should send notifications to it using the xTaskNotifyGive() + * macro, or xTaskNotify() function with the eAction parameter set to + * eIncrement. + * + * ulTaskNotifyTake() can either clear the task's notification value to + * zero on exit, in which case the notification value acts like a binary + * semaphore, or decrement the task's notification value on exit, in which case + * the notification value acts like a counting semaphore. + * + * A task can use ulTaskNotifyTake() to [optionally] block to wait for a + * the task's notification value to be non-zero. The task does not consume any + * CPU time while it is in the Blocked state. + * + * Where as xTaskNotifyWait() will return when a notification is pending, + * ulTaskNotifyTake() will return when the task's notification value is + * not zero. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's + * notification value is decremented when the function exits. In this way the + * notification value acts like a counting semaphore. If xClearCountOnExit is + * not pdFALSE then the task's notification value is cleared to zero when the + * function exits. In this way the notification value acts like a binary + * semaphore. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for the task's notification value to be greater than zero, + * should the count not already be greater than zero when + * ulTaskNotifyTake() was called. The task will not consume any processing + * time while it is in the Blocked state. This is specified in kernel ticks, + * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time + * specified in milliseconds to a time specified in ticks. + * + * @return The task's notification count before it is either cleared to zero or + * decremented (see the xClearCountOnExit parameter). + * + * \defgroup ulTaskNotifyTake ulTaskNotifyTake + * \ingroup TaskNotifications + */ +uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * + * If the notification state of the task referenced by the handle xTask is + * eNotified, then set the task's notification state to eNotWaitingNotification. + * The task's notification value is not altered. Set xTask to NULL to clear the + * notification state of the calling task. + * + * @return pdTRUE if the task's notification state was set to + * eNotWaitingNotification, otherwise pdFALSE. + * \defgroup xTaskNotifyStateClear xTaskNotifyStateClear + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. If a non-zero value is returned then a context switch is + * required because either: + * + A task was removed from a blocked list because its timeout had expired, + * or + * + Time slicing is in use and there is a task of equal priority to the + * currently running task. + */ +BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * The 'unordered' version replaces the event list item value with the + * xItemValue value, and inserts the list item at the end of the list. + * + * The 'ordered' version uses the existing event list item value (which is the + * owning tasks priority) to insert the list item into the event list is task + * priority order. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xItemValue The item value to use for the event list item when the + * event list is not ordered by task priority. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * This function performs nearly the same function as vTaskPlaceOnEventList(). + * The difference being that this function does not permit tasks to block + * indefinitely, whereas vTaskPlaceOnEventList() does. + * + */ +void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called + * if either an event occurs to unblock a task, or the block timeout period + * expires. + * + * xTaskRemoveFromEventList() is used when the event list is in task priority + * order. It removes the list item from the head of the event list as that will + * have the highest priority owning task of all the tasks on the event list. + * xTaskRemoveFromUnorderedEventList() is used when the event list is not + * ordered and the event list items hold something other than the owning tasks + * priority. In this case the event list item value is updated to the value + * passed in the xItemValue parameter. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; + +/* + * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY + * THE EVENT BITS MODULE. + */ +TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; + +/* + * Return the handle of the calling task. + */ +TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. + */ +UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* + * Set the uxTaskNumber of the task referenced by the xTask parameter to + * uxHandle. + */ +void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; + +/* + * Only available when configUSE_TICKLESS_IDLE is set to 1. + * If tickless mode is being used, or a low power mode is implemented, then + * the tick interrupt will not execute during idle periods. When this is the + * case, the tick count value maintained by the scheduler needs to be kept up + * to date with the actual execution time by being skipped forward by a time + * equal to the idle period. + */ +void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; + +/* + * Only avilable when configUSE_TICKLESS_IDLE is set to 1. + * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port + * specific sleep function to determine if it is ok to proceed with the sleep, + * and if it is ok to proceed, if it is ok to sleep indefinitely. + * + * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only + * called with the scheduler suspended, not from within a critical section. It + * is therefore possible for an interrupt to request a context switch between + * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being + * entered. eTaskConfirmSleepModeStatus() should be called from a short + * critical section between the timer being stopped and the sleep mode being + * entered to ensure it is ok to proceed into the sleep mode. + */ +eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Increment the mutex held count when a mutex is + * taken and return the handle of the task that has taken the mutex. + */ +void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* INC_TASK_H */ + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/tasks.c b/STM32F1/libraries/FreeRTOS900/utility/tasks.c new file mode 100644 index 0000000..6c261a6 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/tasks.c @@ -0,0 +1,4807 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "StackMacros.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +/* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting +functions but without including stdio.h here. */ +#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) + /* At the bottom of this file are two optional functions that can be used + to generate human readable text from the raw data generated by the + uxTaskGetSystemState() function. Note the formatting functions are provided + for convenience only, and are NOT considered part of the kernel. */ + #include +#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */ + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define taskYIELD_IF_USING_PREEMPTION() +#else + #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() +#endif + +/* Values that can be assigned to the ucNotifyState member of the TCB. */ +#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) +#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) +#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) + +/* + * The value used to fill the stack of a task when the task is created. This + * is used purely for checking the high water mark for tasks. + */ +#define tskSTACK_FILL_BYTE ( 0xa5U ) + +/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using +dynamically allocated RAM, in which case when any task is deleted it is known +that both the task's stack and TCB need to be freed. Sometimes the +FreeRTOSConfig.h settings only allow a task to be created using statically +allocated RAM, in which case when any task is deleted it is known that neither +the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h +settings allow a task to be created using either statically or dynamically +allocated RAM, in which case a member of the TCB is used to record whether the +stack and/or TCB were allocated statically or dynamically, so when a task is +deleted the RAM that was allocated dynamically is freed again and no attempt is +made to free the RAM that was allocated statically. +tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a +task to be created using either statically or dynamically allocated RAM. Note +that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with +a statically allocated stack and a dynamically allocated TCB. */ +#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) ) +#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 ) +#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 ) +#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskBLOCKED_CHAR ( 'B' ) +#define tskREADY_CHAR ( 'R' ) +#define tskDELETED_CHAR ( 'D' ) +#define tskSUSPENDED_CHAR ( 'S' ) + +/* + * Some kernel aware debuggers require the data the debugger needs access to be + * global, rather than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is + performed in a generic way that is not optimised to any particular + microcontroller architecture. */ + + /* uxTopReadyPriority holds the priority of the highest priority ready + state task. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) \ + { \ + if( ( uxPriority ) > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( uxPriority ); \ + } \ + } /* taskRECORD_READY_PRIORITY */ + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority = uxTopReadyPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \ + { \ + configASSERT( uxTopPriority ); \ + --uxTopPriority; \ + } \ + \ + /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ + the same priority get an equal share of the processor time. */ \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + uxTopReadyPriority = uxTopPriority; \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK */ + + /*-----------------------------------------------------------*/ + + /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as + they are only required when a port optimised method of task selection is + being used. */ + #define taskRESET_READY_PRIORITY( uxPriority ) + #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + +#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is + performed in a way that is tailored to the particular microcontroller + architecture being used. */ + + /* A port optimised version is provided. Call the port defined macros. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority; \ + \ + /* Find the highest priority list that contains ready tasks. */ \ + portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ + configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ + + /*-----------------------------------------------------------*/ + + /* A port optimised version is provided, call it only if the TCB being reset + is being referenced from a ready list. If it is referenced from a delayed + or suspended list then it won't be in a ready list. */ + #define taskRESET_READY_PRIORITY( uxPriority ) \ + { \ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ + { \ + portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ + } \ + } + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick +count overflows. */ +#define taskSWITCH_DELAYED_LISTS() \ +{ \ + List_t *pxTemp; \ + \ + /* The delayed tasks list should be empty when the lists are switched. */ \ + configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ + \ + pxTemp = pxDelayedTaskList; \ + pxDelayedTaskList = pxOverflowDelayedTaskList; \ + pxOverflowDelayedTaskList = pxTemp; \ + xNumOfOverflows++; \ + prvResetNextTaskUnblockTime(); \ +} + +/*-----------------------------------------------------------*/ + +/* + * Place the task represented by pxTCB into the appropriate ready list for + * the task. It is inserted at the end of the list. + */ +#define prvAddTaskToReadyList( pxTCB ) \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ + tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) +/*-----------------------------------------------------------*/ + +/* + * Several functions take an TaskHandle_t parameter that can optionally be NULL, + * where NULL is used to indicate that the handle of the currently executing + * task should be used in place of the parameter. This macro simply checks to + * see if the parameter is NULL and returns a pointer to the appropriate TCB. + */ +#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) ) + +/* The item value of the event list item is normally used to hold the priority +of the task to which it belongs (coded to allow it to be held in reverse +priority order). However, it is occasionally borrowed for other purposes. It +is important its value is not updated due to a task priority change while it is +being used for another purpose. The following bit definition is used to inform +the scheduler that the value should not be changed - in which case it is the +responsibility of whichever module is using the value to ensure it gets set back +to its original value when it is released. */ +#if( configUSE_16_BIT_TICKS == 1 ) + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U +#else + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL +#endif + +/* + * Task control block. A task control block (TCB) is allocated for each task, + * and stores task state information, including a pointer to the task's context + * (the task's run time environment, including register values) + */ +typedef struct tskTaskControlBlock +{ + volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + #endif + + ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ + UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ + StackType_t *pxStack; /*< Points to the start of the stack. */ + char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + + #if ( portSTACK_GROWTH > 0 ) + StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxMutexesHeld; + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t pxTaskTag; + #endif + + #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + + #if( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + /* Allocate a Newlib reent structure that is specific to this task. + Note Newlib support has been included by popular demand, but is not + used by the FreeRTOS maintainers themselves. FreeRTOS is not + responsible for resulting newlib operation. User must be familiar with + newlib and must provide system-wide implementations of the necessary + stubs. Be warned that (at the time of writing) the current newlib design + implements a system-wide malloc() that must be provided with locks. */ + struct _reent xNewLib_reent; + #endif + + #if( configUSE_TASK_NOTIFICATIONS == 1 ) + volatile uint32_t ulNotifiedValue; + volatile uint8_t ucNotifyState; + #endif + + /* See the comments above the definition of + tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ + #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ + #endif + + #if( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDelayAborted; + #endif + +} tskTCB; + +/* The old tskTCB name is maintained above then typedefed to the new TCB_t name +below to enable the use of older kernel aware debuggers. */ +typedef tskTCB TCB_t; + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; + +/* Lists for ready and blocked tasks. --------------------*/ +PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + +#if( INCLUDE_vTaskDelete == 1 ) + + PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */ + PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U; + +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + + PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ + +#endif + +/* Other file private variables. --------------------------------*/ +PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U; +PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; +PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE; +PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; +PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */ +PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ + +/* Context switches are held pending while the scheduler is suspended. Also, +interrupts must not manipulate the xStateListItem of a TCB, or any of the +lists the xStateListItem can be referenced from, if the scheduler is suspended. +If an interrupt needs to unblock a task while the scheduler is suspended then it +moves the task's event list item into the xPendingReadyList, ready for the +kernel to move the task from the pending ready list into the real ready list +when the scheduler is unsuspended. The pending ready list itself can only be +accessed from a critical section. */ +PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ + +#endif + +/*lint +e956 */ + +/*-----------------------------------------------------------*/ + +/* Callback function prototypes. --------------------------*/ +#if( configCHECK_FOR_STACK_OVERFLOW > 0 ) + extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); +#endif + +#if( configUSE_TICK_HOOK > 0 ) + extern void vApplicationTickHook( void ); +#endif + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); +#endif + +/* File private functions. --------------------------------*/ + +/** + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. + */ +#if ( INCLUDE_vTaskSuspend == 1 ) + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#endif /* INCLUDE_vTaskSuspend */ + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first task. + */ +static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; + +/* + * The idle task, which as all tasks is implemented as a never ending loop. + * The idle task is automatically created and added to the ready lists upon + * creation of the first user task. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); + +/* + * Utility to free all memory allocated by the scheduler to hold a TCB, + * including the stack pointed to by the TCB. + * + * This does not free memory allocated by the task itself (i.e. memory + * allocated by calls to pvPortMalloc from within the tasks application code). + */ +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Used only by the idle task. This checks to see if anything has been placed + * in the list of tasks waiting to be deleted. If so the task is cleaned up + * and its TCB deleted. + */ +static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; + +/* + * The currently executing task is entering the Blocked state. Add the task to + * either the current or the overflow delayed task list. + */ +static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION; + +/* + * Fills an TaskStatus_t structure with information on each task that is + * referenced from the pxList list (which may be a ready list, a delayed list, + * a suspended list, etc.). + * + * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM + * NORMAL APPLICATION CODE. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Searches pxList for a task with name pcNameToQuery - returning a handle to + * the task if it is found, or NULL if the task is not found. + */ +#if ( INCLUDE_xTaskGetHandle == 1 ) + + static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION; + +#endif + +/* + * When a task is created, the stack of the task is filled with a known value. + * This function determines the 'high water mark' of the task stack by + * determining how much of the stack remains at the original preset value. + */ +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Return the amount of time, in ticks, that will pass before the kernel will + * next move a task from the Blocked state to the Running state. + * + * This conditional compilation should use inequality to 0, not equality to 1. + * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user + * defined low power mode implementations require configUSE_TICKLESS_IDLE to be + * set to a value other than 1. + */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Set xNextTaskUnblockTime to the time at which the next Blocked state task + * will exit the Blocked state. + */ +static void prvResetNextTaskUnblockTime( void ); + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + /* + * Helper function used to pad task names with spaces when printing out + * human readable tables of task information. + */ + static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Called after a Task_t structure has been allocated either statically or + * dynamically to fill in the structure's members. + */ +static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask, + TCB_t *pxNewTCB, + const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/* + * Called after a new task has been created and initialised to place the task + * under the control of the scheduler. + */ +static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + TCB_t *pxNewTCB; + TaskHandle_t xReturn; + + configASSERT( puxStackBuffer != NULL ); + configASSERT( pxTaskBuffer != NULL ); + + if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) ) + { + /* The memory used for the task's TCB and stack are passed into this + function - use them. */ + pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer; + + #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL ); + prvAddNewTaskToReadyList( pxNewTCB ); + } + else + { + xReturn = NULL; + } + + return xReturn; + } + +#endif /* SUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( portUSING_MPU_WRAPPERS == 1 ) + + BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) + { + TCB_t *pxNewTCB; + BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + + configASSERT( pxTaskDefinition->puxStackBuffer ); + + if( pxTaskDefinition->puxStackBuffer != NULL ) + { + /* Allocate space for the TCB. Where the memory comes from depends + on the implementation of the port malloc function and whether or + not static allocation is being used. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; + + /* Tasks can be created statically or dynamically, so note + this task had a statically allocated stack in case it is + later deleted. The TCB was allocated dynamically. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; + + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions ); + + prvAddNewTaskToReadyList( pxNewTCB ); + xReturn = pdPASS; + } + } + + return xReturn; + } + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + TCB_t *pxNewTCB; + BaseType_t xReturn; + + /* If the stack grows down then allocate the stack then the TCB so the stack + does not grow into the TCB. Likewise if the stack grows up then allocate + the TCB then the stack. */ + #if( portSTACK_GROWTH > 0 ) + { + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function and whether or not static + allocation is being used. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + } + } + #else /* portSTACK_GROWTH */ + { + StackType_t *pxStack; + + /* Allocate space for the stack used by the task being created. */ + pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxStack != NULL ) + { + /* Allocate space for the TCB. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */ + + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxStack; + } + else + { + /* The stack cannot be used as the TCB was not created. Free + it again. */ + vPortFree( pxStack ); + } + } + else + { + pxNewTCB = NULL; + } + } + #endif /* portSTACK_GROWTH */ + + if( pxNewTCB != NULL ) + { + #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + task was created dynamically in case it is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL ); + prvAddNewTaskToReadyList( pxNewTCB ); + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; + } + +#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask, + TCB_t *pxNewTCB, + const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +StackType_t *pxTopOfStack; +UBaseType_t x; + + #if( portUSING_MPU_WRAPPERS == 1 ) + /* Should the task be created in privileged mode? */ + BaseType_t xRunPrivileged; + if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) + { + xRunPrivileged = pdTRUE; + } + else + { + xRunPrivileged = pdFALSE; + } + uxPriority &= ~portPRIVILEGE_BIT; + #endif /* portUSING_MPU_WRAPPERS == 1 */ + + /* Avoid dependency on memset() if it is not required. */ + #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + { + /* Fill the stack with a known value to assist debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); + } + #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */ + + /* Calculate the top of stack address. This depends on whether the stack + grows from high memory to low (as per the 80x86) or vice versa. + portSTACK_GROWTH is used to make the result positive or negative as required + by the port. */ + #if( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */ + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + } + #else /* portSTACK_GROWTH */ + { + pxTopOfStack = pxNewTCB->pxStack; + + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + /* The other extreme of the stack space is required if stack checking is + performed. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); + } + #endif /* portSTACK_GROWTH */ + + /* Store the task name in the TCB. */ + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + pxNewTCB->pcTaskName[ x ] = pcName[ x ]; + + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + configMAX_TASK_NAME_LEN characters just in case the memory after the + string is not accessible (extremely unlikely). */ + if( pcName[ x ] == 0x00 ) + { + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Ensure the name string is terminated in the case that the string length + was greater or equal to configMAX_TASK_NAME_LEN. */ + pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + + /* This is used as an array index so must ensure it's not too large. First + remove the privilege bit if one is present. */ + if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxNewTCB->uxPriority = uxPriority; + #if ( configUSE_MUTEXES == 1 ) + { + pxNewTCB->uxBasePriority = uxPriority; + pxNewTCB->uxMutexesHeld = 0; + } + #endif /* configUSE_MUTEXES */ + + vListInitialiseItem( &( pxNewTCB->xStateListItem ) ); + vListInitialiseItem( &( pxNewTCB->xEventListItem ) ); + + /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get + back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB ); + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; + } + #endif /* portCRITICAL_NESTING_IN_TCB */ + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxNewTCB->pxTaskTag = NULL; + } + #endif /* configUSE_APPLICATION_TASK_TAG */ + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxNewTCB->ulRunTimeCounter = 0UL; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth ); + } + #else + { + /* Avoid compiler warning about unreferenced parameter. */ + ( void ) xRegions; + } + #endif + + #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + { + for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) + { + pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL; + } + } + #endif + + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + pxNewTCB->ulNotifiedValue = 0; + pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + } + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Initialise this task's Newlib reent structure. */ + _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); + } + #endif + + #if( INCLUDE_xTaskAbortDelay == 1 ) + { + pxNewTCB->ucDelayAborted = pdFALSE; + } + #endif + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + #if( portUSING_MPU_WRAPPERS == 1 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portUSING_MPU_WRAPPERS */ + + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the handle out in an anonymous way. The handle can be used to + change the created task's priority, delete the created task, etc.*/ + *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} +/*-----------------------------------------------------------*/ + +static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) +{ + /* Ensure interrupts don't access the task lists while the lists are being + updated. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + if( pxCurrentTCB == NULL ) + { + /* There are no other tasks, or all the other tasks are in + the suspended state - make this the current task. */ + pxCurrentTCB = pxNewTCB; + + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If the scheduler is not already running, make this task the + current task if it is the highest priority task to be created + so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ) + { + pxCurrentTCB = pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + uxTaskNumber++; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); + + prvAddTaskToReadyList( pxNewTCB ); + + portSETUP_TCB( pxNewTCB ); + } + taskEXIT_CRITICAL(); + + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than the current task + then it should run now. */ + if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + void vTaskDelete( TaskHandle_t xTaskToDelete ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the calling task that is + being deleted. */ + pxTCB = prvGetTCBFromHandle( xTaskToDelete ); + + /* Remove task from the ready list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Increment the uxTaskNumber also so kernel aware debuggers can + detect that the task lists need re-generating. This is done before + portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will + not return. */ + uxTaskNumber++; + + if( pxTCB == pxCurrentTCB ) + { + /* A task is deleting itself. This cannot complete within the + task itself, as a context switch to another task is required. + Place the task in the termination list. The idle task will + check the termination list and free up any memory allocated by + the scheduler for the TCB and stack of the deleted task. */ + vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxDeletedTasksWaitingCleanUp; + + /* The pre-delete hook is primarily for the Windows simulator, + in which Windows specific clean up operations are performed, + after which it is not possible to yield away from this task - + hence xYieldPending is used to latch that a context switch is + required. */ + portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); + } + else + { + --uxCurrentNumberOfTasks; + prvDeleteTCB( pxTCB ); + + /* Reset the next expected unblock time in case it referred to + the task that has just been deleted. */ + prvResetNextTaskUnblockTime(); + } + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); + + /* Force a reschedule if it is the currently running task that has just + been deleted. */ + if( xSchedulerRunning != pdFALSE ) + { + if( pxTCB == pxCurrentTCB ) + { + configASSERT( uxSchedulerSuspended == 0 ); + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + + void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) + { + TickType_t xTimeToWake; + BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; + + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + configASSERT( uxSchedulerSuspended == 0 ); + + vTaskSuspendAll(); + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const TickType_t xConstTickCount = xTickCount; + + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + + if( xConstTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; + + if( xShouldDelay != pdFALSE ) + { + traceTASK_DELAY_UNTIL( xTimeToWake ); + + /* prvAddCurrentTaskToDelayedList() needs the block time, not + the time to wake, so subtract the current tick count. */ + prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + xAlreadyYielded = xTaskResumeAll(); + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskDelayUntil */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + + void vTaskDelay( const TickType_t xTicksToDelay ) + { + BaseType_t xAlreadyYielded = pdFALSE; + + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( TickType_t ) 0U ) + { + configASSERT( uxSchedulerSuspended == 0 ); + vTaskSuspendAll(); + { + traceTASK_DELAY(); + + /* A task that is removed from the event list while the + scheduler is suspended will not get placed in the ready + list or removed from the blocked list until the scheduler + is resumed. + + This task cannot be in an event list as it is the currently + executing task. */ + prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); + } + xAlreadyYielded = xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskDelay */ +/*-----------------------------------------------------------*/ + +#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) ) + + eTaskState eTaskGetState( TaskHandle_t xTask ) + { + eTaskState eReturn; + List_t *pxStateList; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + configASSERT( pxTCB ); + + if( pxTCB == pxCurrentTCB ) + { + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + else + { + taskENTER_CRITICAL(); + { + pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); + } + taskEXIT_CRITICAL(); + + if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) ) + { + /* The task being queried is referenced from one of the Blocked + lists. */ + eReturn = eBlocked; + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( pxStateList == &xSuspendedTaskList ) + { + /* The task being queried is referenced from the suspended + list. Is it genuinely suspended or is it block + indefinitely? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + { + eReturn = eSuspended; + } + else + { + eReturn = eBlocked; + } + } + #endif + + #if ( INCLUDE_vTaskDelete == 1 ) + else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) ) + { + /* The task being queried is referenced from the deleted + tasks list, or it is not referenced from any lists at + all. */ + eReturn = eDeleted; + } + #endif + + else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ + { + /* If the task is not in any other state, it must be in the + Ready (including pending ready) state. */ + eReturn = eReady; + } + } + + return eReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_eTaskGetState */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + UBaseType_t uxReturn; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the priority of the that + called uxTaskPriorityGet() that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + UBaseType_t uxReturn, uxSavedInterruptState; + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* If null is passed in here then it is the priority of the calling + task that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + + void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) + { + TCB_t *pxTCB; + UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; + BaseType_t xYieldRequired = pdFALSE; + + configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + + /* Ensure the new priority is valid. */ + if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the priority of the calling + task that is being changed. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); + + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentBasePriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentBasePriority = pxTCB->uxPriority; + } + #endif + + if( uxCurrentBasePriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + priority than the calling task. */ + if( uxNewPriority > uxCurrentBasePriority ) + { + if( pxTCB != pxCurrentTCB ) + { + /* The priority of a task other than the currently + running task is being raised. Is the priority being + raised above that of the running task? */ + if( uxNewPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The priority of the running task is being raised, + but the running task must already be the highest + priority task able to run so no yield is required. */ + } + } + else if( pxTCB == pxCurrentTCB ) + { + /* Setting the priority of the running task down means + there may now be another task of higher priority that + is ready to execute. */ + xYieldRequired = pdTRUE; + } + else + { + /* Setting the priority of any other task down does not + require a yield as the running task must be above the + new priority of the task being modified. */ + } + + /* Remember the ready list the task might be referenced from + before its uxPriority member is changed so the + taskRESET_READY_PRIORITY() macro can function correctly. */ + uxPriorityUsedOnEntry = pxTCB->uxPriority; + + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else + { + pxTCB->uxPriority = uxNewPriority; + } + #endif + + /* Only reset the event list item value if the value is not + being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* If the task is in the blocked or suspended list we need do + nothing more than change it's priority variable. However, if + the task is in a ready list it needs to be removed and placed + in the list appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) + { + /* The task is currently in its ready list - remove before adding + it to it's new ready list. As we are in a critical section we + can do this even if the scheduler is suspended. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* It is known that the task is in its ready list so + there is no need to check again and the port level + reset macro can be called directly. */ + portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvAddTaskToReadyList( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xYieldRequired != pdFALSE ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Remove compiler warning about unused variables when the port + optimised task selection is not being used. */ + ( void ) uxPriorityUsedOnEntry; + } + } + taskEXIT_CRITICAL(); + } + +#endif /* INCLUDE_vTaskPrioritySet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskSuspend( TaskHandle_t xTaskToSuspend ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the running task that is + being suspended. */ + pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); + + traceTASK_SUSPEND( pxTCB ); + + /* Remove task from the ready/delayed list and place in the + suspended list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); + } + taskEXIT_CRITICAL(); + + if( xSchedulerRunning != pdFALSE ) + { + /* Reset the next expected unblock time in case it referred to the + task that is now in the Suspended state. */ + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( pxTCB == pxCurrentTCB ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* The current task has just been suspended. */ + configASSERT( uxSchedulerSuspended == 0 ); + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + to by pxCurrentTCB has just been suspended and pxCurrentTCB + must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + { + /* No other tasks are ready, so set pxCurrentTCB back to + NULL so when the next task is created pxCurrentTCB will + be set to point to it no matter what its relative priority + is. */ + pxCurrentTCB = NULL; + } + else + { + vTaskSwitchContext(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) + { + BaseType_t xReturn = pdFALSE; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + /* Accesses xPendingReadyList so must be called from a critical + section. */ + + /* It does not make sense to check if the calling task is suspended. */ + configASSERT( xTask ); + + /* Is the task being resumed actually in the suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) + { + /* Is it in the suspended list because it is in the Suspended + state, or because is is blocked with no timeout? */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) + { + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskResume( TaskHandle_t xTaskToResume ) + { + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + + /* It does not make sense to resume the calling task. */ + configASSERT( xTaskToResume ); + + /* The parameter cannot be NULL as it is impossible to resume the + currently executing task. */ + if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) + { + taskENTER_CRITICAL(); + { + if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) + { + traceTASK_RESUME( pxTCB ); + + /* As we are in a critical section we can access the ready + lists even if the scheduler is suspended. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* This yield may not cause the task just resumed to run, + but will leave the lists in the correct state for the + next yield. */ + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskSuspend */ + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + + BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) + { + BaseType_t xYieldRequired = pdFALSE; + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( xTaskToResume ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); + + /* Check the ready lists can be accessed. */ + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + /* Ready lists can be accessed so move the task from the + suspended list to the ready list directly. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed or ready lists cannot be accessed so the task + is held in the pending ready list until the scheduler is + unsuspended. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xYieldRequired; + } + +#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ +/*-----------------------------------------------------------*/ + +void vTaskStartScheduler( void ) +{ +BaseType_t xReturn; + + /* Add the idle task at the lowest priority. */ + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + StaticTask_t *pxIdleTaskTCBBuffer = NULL; + StackType_t *pxIdleTaskStackBuffer = NULL; + uint32_t ulIdleTaskStackSize; + + /* The Idle task is created using user provided RAM - obtain the + address of the RAM then create the idle task. */ + vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize ); + xIdleTaskHandle = xTaskCreateStatic( prvIdleTask, + "IDLE", + ulIdleTaskStackSize, + ( void * ) NULL, + ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), + pxIdleTaskStackBuffer, + pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + + if( xIdleTaskHandle != NULL ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + #else + { + /* The Idle task is being created using dynamically allocated RAM. */ + xReturn = xTaskCreate( prvIdleTask, + "IDLE", configMINIMAL_STACK_SIZE, + ( void * ) NULL, + ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), + &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + #if ( configUSE_TIMERS == 1 ) + { + if( xReturn == pdPASS ) + { + xReturn = xTimerCreateTimerTask(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TIMERS */ + + if( xReturn == pdPASS ) + { + /* Interrupts are turned off here, to ensure a tick does not occur + before or during the call to xPortStartScheduler(). The stacks of + the created tasks contain a status word with interrupts switched on + so interrupts will automatically get re-enabled when the first task + starts to run. */ + portDISABLE_INTERRUPTS(); + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to the task that will run first. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + xNextTaskUnblockTime = portMAX_DELAY; + xSchedulerRunning = pdTRUE; + xTickCount = ( TickType_t ) 0U; + + /* If configGENERATE_RUN_TIME_STATS is defined then the following + macro must be defined to configure the timer/counter used to generate + the run time counter time base. */ + portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + + /* Setting up the timer tick is hardware specific and thus in the + portable interface. */ + if( xPortStartScheduler() != pdFALSE ) + { + /* Should not reach here as if the scheduler is running the + function will not return. */ + } + else + { + /* Should only reach here if a task calls xTaskEndScheduler(). */ + } + } + else + { + /* This line will only be reached if the kernel could not be started, + because there was not enough FreeRTOS heap to create the idle task + or the timer task. */ + configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ); + } + + /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0, + meaning xIdleTaskHandle is not used anywhere else. */ + ( void ) xIdleTaskHandle; +} +/*-----------------------------------------------------------*/ + +void vTaskEndScheduler( void ) +{ + /* Stop the scheduler interrupts and call the portable scheduler end + routine so the original ISRs can be restored if necessary. The port + layer must ensure interrupts enable bit is left in the correct state. */ + portDISABLE_INTERRUPTS(); + xSchedulerRunning = pdFALSE; + vPortEndScheduler(); +} +/*----------------------------------------------------------*/ + +void vTaskSuspendAll( void ) +{ + /* A critical section is not required as the variable is of type + BaseType_t. Please read Richard Barry's reply in the following link to a + post in the FreeRTOS support forum before reporting this as a bug! - + http://goo.gl/wu4acr */ + ++uxSchedulerSuspended; +} +/*----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static TickType_t prvGetExpectedIdleTime( void ) + { + TickType_t xReturn; + UBaseType_t uxHigherPriorityReadyTasks = pdFALSE; + + /* uxHigherPriorityReadyTasks takes care of the case where + configUSE_PREEMPTION is 0, so there may be tasks above the idle priority + task that are in the Ready state, even though the idle task is + running. */ + #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) + { + if( uxTopReadyPriority > tskIDLE_PRIORITY ) + { + uxHigherPriorityReadyTasks = pdTRUE; + } + } + #else + { + const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01; + + /* When port optimised task selection is used the uxTopReadyPriority + variable is used as a bit map. If bits other than the least + significant bit are set then there are tasks that have a priority + above the idle priority that are in the Ready state. This takes + care of the case where the co-operative scheduler is in use. */ + if( uxTopReadyPriority > uxLeastSignificantBit ) + { + uxHigherPriorityReadyTasks = pdTRUE; + } + } + #endif + + if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) + { + xReturn = 0; + } + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + { + /* There are other idle priority tasks in the ready state. If + time slicing is used then the very next tick interrupt must be + processed. */ + xReturn = 0; + } + else if( uxHigherPriorityReadyTasks != pdFALSE ) + { + /* There are tasks in the Ready state that have a priority above the + idle priority. This path can only be reached if + configUSE_PREEMPTION is 0. */ + xReturn = 0; + } + else + { + xReturn = xNextTaskUnblockTime - xTickCount; + } + + return xReturn; + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +BaseType_t xTaskResumeAll( void ) +{ +TCB_t *pxTCB = NULL; +BaseType_t xAlreadyYielded = pdFALSE; + + /* If uxSchedulerSuspended is zero then this function does not match a + previous call to vTaskSuspendAll(). */ + configASSERT( uxSchedulerSuspended ); + + /* It is possible that an ISR caused a task to be removed from an event + list while the scheduler was suspended. If this was the case then the + removed task will have been added to the xPendingReadyList. Once the + scheduler has been resumed it is safe to move all the pending ready + tasks from this list into their appropriate ready list. */ + taskENTER_CRITICAL(); + { + --uxSchedulerSuspended; + + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) + { + /* Move any readied tasks from the pending list into the + appropriate ready list. */ + while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) + { + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* If the moved task has a priority higher than the current + task then a yield must be performed. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + if( pxTCB != NULL ) + { + /* A task was unblocked while the scheduler was suspended, + which may have prevented the next unblock time from being + re-calculated, in which case re-calculate it now. Mainly + important for low power tickless implementations, where + this can prevent an unnecessary exit from low power + state. */ + prvResetNextTaskUnblockTime(); + } + + /* If any ticks occurred while the scheduler was suspended then + they should be processed now. This ensures the tick count does + not slip, and that any delayed tasks are resumed at the correct + time. */ + { + UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */ + + if( uxPendedCounts > ( UBaseType_t ) 0U ) + { + do + { + if( xTaskIncrementTick() != pdFALSE ) + { + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --uxPendedCounts; + } while( uxPendedCounts > ( UBaseType_t ) 0U ); + + uxPendedTicks = 0; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + if( xYieldPending != pdFALSE ) + { + #if( configUSE_PREEMPTION != 0 ) + { + xAlreadyYielded = pdTRUE; + } + #endif + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + return xAlreadyYielded; +} +/*-----------------------------------------------------------*/ + +TickType_t xTaskGetTickCount( void ) +{ +TickType_t xTicks; + + /* Critical section required if running on a 16 bit processor. */ + portTICK_TYPE_ENTER_CRITICAL(); + { + xTicks = xTickCount; + } + portTICK_TYPE_EXIT_CRITICAL(); + + return xTicks; +} +/*-----------------------------------------------------------*/ + +TickType_t xTaskGetTickCountFromISR( void ) +{ +TickType_t xReturn; +UBaseType_t uxSavedInterruptStatus; + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR(); + { + xReturn = xTickCount; + } + portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxTaskGetNumberOfTasks( void ) +{ + /* A critical section is not required because the variables are of type + BaseType_t. */ + return uxCurrentNumberOfTasks; +} +/*-----------------------------------------------------------*/ + +char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +TCB_t *pxTCB; + + /* If null is passed in here then the name of the calling task is being + queried. */ + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + configASSERT( pxTCB ); + return &( pxTCB->pcTaskName[ 0 ] ); +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetHandle == 1 ) + + static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) + { + TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL; + UBaseType_t x; + char cNextChar; + + /* This function is called with the scheduler suspended. */ + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + /* Check each character in the name looking for a match or + mismatch. */ + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + cNextChar = pxNextTCB->pcTaskName[ x ]; + + if( cNextChar != pcNameToQuery[ x ] ) + { + /* Characters didn't match. */ + break; + } + else if( cNextChar == 0x00 ) + { + /* Both strings terminated, a match must have been + found. */ + pxReturn = pxNextTCB; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + if( pxReturn != NULL ) + { + /* The handle has been found. */ + break; + } + + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return pxReturn; + } + +#endif /* INCLUDE_xTaskGetHandle */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetHandle == 1 ) + + TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t uxQueue = configMAX_PRIORITIES; + TCB_t* pxTCB; + + /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ + configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); + + vTaskSuspendAll(); + { + /* Search the ready lists. */ + do + { + uxQueue--; + pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery ); + + if( pxTCB != NULL ) + { + /* Found the handle. */ + break; + } + + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Search the delayed lists. */ + if( pxTCB == NULL ) + { + pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery ); + } + + if( pxTCB == NULL ) + { + pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery ); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( pxTCB == NULL ) + { + /* Search the suspended list. */ + pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); + } + } + #endif + + #if( INCLUDE_vTaskDelete == 1 ) + { + if( pxTCB == NULL ) + { + /* Search the deleted list. */ + pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); + } + } + #endif + } + ( void ) xTaskResumeAll(); + + return ( TaskHandle_t ) pxTCB; + } + +#endif /* INCLUDE_xTaskGetHandle */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) + { + UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + + vTaskSuspendAll(); + { + /* Is there a space in the array for each task in the system? */ + if( uxArraySize >= uxCurrentNumberOfTasks ) + { + /* Fill in an TaskStatus_t structure with information on each + task in the Ready state. */ + do + { + uxQueue--; + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); + + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an TaskStatus_t structure with information on each + task in the Blocked state. */ + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); + + #if( INCLUDE_vTaskDelete == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + each task that has been deleted but not yet cleaned up. */ + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + each task in the Suspended state. */ + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1) + { + if( pulTotalRunTime != NULL ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + } + } + #else + { + if( pulTotalRunTime != NULL ) + { + *pulTotalRunTime = 0; + } + } + #endif + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + ( void ) xTaskResumeAll(); + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + TaskHandle_t xTaskGetIdleTaskHandle( void ) + { + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + started, then xIdleTaskHandle will be NULL. */ + configASSERT( ( xIdleTaskHandle != NULL ) ); + return xIdleTaskHandle; + } + +#endif /* INCLUDE_xTaskGetIdleTaskHandle */ +/*----------------------------------------------------------*/ + +/* This conditional compilation should use inequality to 0, not equality to 1. +This is to ensure vTaskStepTick() is available when user defined low power mode +implementations require configUSE_TICKLESS_IDLE to be set to a value other than +1. */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + void vTaskStepTick( const TickType_t xTicksToJump ) + { + /* Correct the tick count value after a period during which the tick + was suppressed. Note this does *not* call the tick hook function for + each stepped tick. */ + configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); + xTickCount += xTicksToJump; + traceINCREASE_TICK_COUNT( xTicksToJump ); + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskAbortDelay == 1 ) + + BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) + { + TCB_t *pxTCB = ( TCB_t * ) xTask; + BaseType_t xReturn = pdFALSE; + + configASSERT( pxTCB ); + + vTaskSuspendAll(); + { + /* A task can only be prematurely removed from the Blocked state if + it is actually in the Blocked state. */ + if( eTaskGetState( xTask ) == eBlocked ) + { + /* Remove the reference to the task from the blocked list. An + interrupt won't touch the xStateListItem because the + scheduler is suspended. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + + /* Is the task waiting on an event also? If so remove it from + the event list too. Interrupts can touch the event list item, + even though the scheduler is suspended, so a critical section + is used. */ + taskENTER_CRITICAL(); + { + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + pxTCB->ucDelayAborted = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + /* Place the unblocked task into the appropriate ready list. */ + prvAddTaskToReadyList( pxTCB ); + + /* A task being unblocked cannot cause an immediate context + switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should only be + performed if the unblocked task has a priority that is + equal to or higher than the currently executing task. */ + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Pend the yield to be performed when the scheduler + is unsuspended. */ + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + xTaskResumeAll(); + + return xReturn; + } + +#endif /* INCLUDE_xTaskAbortDelay */ +/*----------------------------------------------------------*/ + +BaseType_t xTaskIncrementTick( void ) +{ +TCB_t * pxTCB; +TickType_t xItemValue; +BaseType_t xSwitchRequired = pdFALSE; + + /* Called by the portable layer each time a tick interrupt occurs. + Increments the tick then checks to see if the new tick value will cause any + tasks to be unblocked. */ + traceTASK_INCREMENT_TICK( xTickCount ); + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const TickType_t xConstTickCount = xTickCount + 1; + + /* Increment the RTOS tick, switching the delayed and overflowed + delayed lists if it wraps to 0. */ + xTickCount = xConstTickCount; + + if( xConstTickCount == ( TickType_t ) 0U ) + { + taskSWITCH_DELAYED_LISTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* See if this tick has made a timeout expire. Tasks are stored in + the queue in the order of their wake time - meaning once one task + has been found whose block time has not expired there is no need to + look any further down the list. */ + if( xConstTickCount >= xNextTaskUnblockTime ) + { + for( ;; ) + { + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The delayed list is empty. Set xNextTaskUnblockTime + to the maximum possible value so it is extremely + unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass + next time through. */ + xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + break; + } + else + { + /* The delayed list is not empty, get the value of the + item at the head of the delayed list. This is the time + at which the task at the head of the delayed list must + be removed from the Blocked state. */ + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); + + if( xConstTickCount < xItemValue ) + { + /* It is not time to unblock this item yet, but the + item value is the time at which the task at the head + of the blocked list must be removed from the Blocked + state - so record the item value in + xNextTaskUnblockTime. */ + xNextTaskUnblockTime = xItemValue; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* It is time to remove the item from the Blocked state. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + + /* Is the task waiting on an event also? If so remove + it from the event list. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Place the unblocked task into the appropriate ready + list. */ + prvAddTaskToReadyList( pxTCB ); + + /* A task being unblocked cannot cause an immediate + context switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should + only be performed if the unblocked task has a + priority that is equal to or higher than the + currently executing task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + } + } + } + + /* Tasks of equal priority to the currently running task will share + processing time (time slice) if preemption is on, and the application + writer has not explicitly turned time slicing off. */ + #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ + + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the pended tick + count is being unwound (when the scheduler is being unlocked). */ + if( uxPendedTicks == ( UBaseType_t ) 0U ) + { + vApplicationTickHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICK_HOOK */ + } + else + { + ++uxPendedTicks; + + /* The tick hook gets called at regular intervals, even if the + scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + vApplicationTickHook(); + } + #endif + } + + #if ( configUSE_PREEMPTION == 1 ) + { + if( xYieldPending != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + + return xSwitchRequired; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) + { + TCB_t *xTCB; + + /* If xTask is NULL then it is the task hook of the calling task that is + getting set. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + xTCB->pxTaskTag = pxHookFunction; + taskEXIT_CRITICAL(); + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) + { + TCB_t *xTCB; + TaskHookFunction_t xReturn; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + { + xReturn = xTCB->pxTaskTag; + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) + { + TCB_t *xTCB; + BaseType_t xReturn; + + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +void vTaskSwitchContext( void ) +{ + if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + switch. */ + xYieldPending = pdTRUE; + } + else + { + xYieldPending = pdFALSE; + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Add the amount of time the task has been running to the + accumulated time so far. The time the task started running was + stored in ulTaskSwitchedInTime. Note that there is no overflow + protection here so count values are only valid until the timer + overflows. The guard against negative values is to protect + against suspect run time stat counter implementations - which + are provided by the application, not the kernel. */ + if( ulTotalRunTime > ulTaskSwitchedInTime ) + { + pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ulTaskSwitchedInTime = ulTotalRunTime; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + /* Check for stack overflow, if configured. */ + taskCHECK_FOR_STACK_OVERFLOW(); + + /* Select a new task to run using either the generic C or port + optimised asm code. */ + taskSELECT_HIGHEST_PRIORITY_TASK(); + traceTASK_SWITCHED_IN(); + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to this task. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + } +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) +{ + configASSERT( pxEventList ); + + /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ + + /* Place the event list item of the TCB in the appropriate event list. + This is placed in the list in priority order so the highest priority task + is the first to be woken by the event. The queue that contains the event + list is locked, preventing simultaneous access from interrupts. */ + vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) +{ + configASSERT( pxEventList ); + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event groups implementation. */ + configASSERT( uxSchedulerSuspended != 0 ); + + /* Store the item value in the event list item. It is safe to access the + event list item here as interrupts won't access the event list item of a + task that is not in the Blocked state. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Place the event list item of the TCB at the end of the appropriate event + list. It is safe to access the event list here because it is part of an + event group implementation - and interrupts don't access event groups + directly (instead they access them indirectly by pending function calls to + the task level). */ + vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); +} +/*-----------------------------------------------------------*/ + +#if( configUSE_TIMERS == 1 ) + + void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) + { + configASSERT( pxEventList ); + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements - + it should be called with the scheduler suspended. */ + + + /* Place the event list item of the TCB in the appropriate event list. + In this case it is assume that this is the only task that is going to + be waiting on this event list, so the faster vListInsertEnd() function + can be used in place of vListInsert. */ + vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + /* If the task should block indefinitely then set the block time to a + value that will be recognised as an indefinite delay inside the + prvAddCurrentTaskToDelayedList() function. */ + if( xWaitIndefinitely != pdFALSE ) + { + xTicksToWait = portMAX_DELAY; + } + + traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) ); + prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be + called from a critical section within an ISR. */ + + /* The event list is sorted in priority order, so the first in the list can + be removed as it is known to be the highest priority. Remove the TCB from + the delayed list, and add it to the ready list. + + If an event is for a queue that is locked then this function will never + get called - the lock count on the queue will get modified instead. This + means exclusive access to the event list is guaranteed here. + + This function assumes that a check has already been made to ensure that + pxEventList is not empty. */ + pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); + + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold this task + pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + } + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has a higher + priority than the calling task. This allows the calling task to know if + it should force a context switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event flags implementation. */ + configASSERT( uxSchedulerSuspended != pdFALSE ); + + /* Store the new item value in the event list. */ + listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Remove the event list form the event flag. Interrupts do not access + event flags. */ + pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( pxEventListItem ); + + /* Remove the task from the delayed list and add it to the ready list. The + scheduler is suspended so interrupts will not be accessing the ready + lists. */ + ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has + a higher priority than the calling task. This allows + the calling task to know if it should force a context + switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) +{ + configASSERT( pxTimeOut ); + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) +{ +BaseType_t xReturn; + + configASSERT( pxTimeOut ); + configASSERT( pxTicksToWait ); + + taskENTER_CRITICAL(); + { + /* Minor optimisation. The tick count cannot change in this block. */ + const TickType_t xConstTickCount = xTickCount; + + #if( INCLUDE_xTaskAbortDelay == 1 ) + if( pxCurrentTCB->ucDelayAborted != pdFALSE ) + { + /* The delay was aborted, which is not the same as a time out, + but has the same result. */ + pxCurrentTCB->ucDelayAborted = pdFALSE; + xReturn = pdTRUE; + } + else + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + if( *pxTicksToWait == portMAX_DELAY ) + { + /* If INCLUDE_vTaskSuspend is set to 1 and the block time + specified is the maximum block time then the task should block + indefinitely, and therefore never time out. */ + xReturn = pdFALSE; + } + else + #endif + + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ + { + /* The tick count is greater than the time at which + vTaskSetTimeout() was called, but has also overflowed since + vTaskSetTimeOut() was called. It must have wrapped all the way + around and gone past again. This passed since vTaskSetTimeout() + was called. */ + xReturn = pdTRUE; + } + else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); + vTaskSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskMissedYield( void ) +{ + xYieldPending = pdTRUE; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) + { + UBaseType_t uxReturn; + TCB_t *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( TCB_t * ) xTask; + uxReturn = pxTCB->uxTaskNumber; + } + else + { + uxReturn = 0U; + } + + return uxReturn; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) + { + TCB_t *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( TCB_t * ) xTask; + pxTCB->uxTaskNumber = uxHandle; + } + } + +#endif /* configUSE_TRACE_FACILITY */ + +/* + * ----------------------------------------------------------- + * The Idle task. + * ---------------------------------------------------------- + * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION( prvIdleTask, pvParameters ) +{ + /* Stop warnings. */ + ( void ) pvParameters; + + /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE + SCHEDULER IS STARTED. **/ + + for( ;; ) + { + /* See if any tasks have deleted themselves - if so then the idle task + is responsible for freeing the deleted task's TCB and stack. */ + prvCheckTasksWaitingTermination(); + + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + see if any other task has become available. If we are using + preemption we don't need to do this as any task becoming available + will automatically get the processor anyway. */ + taskYIELD(); + } + #endif /* configUSE_PREEMPTION */ + + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + timesliced. If a task that is sharing the idle priority is ready + to run then the idle task should yield before the end of the + timeslice. + + A critical region is not required here as we are just reading from + the list, and an occasional incorrect value will not matter. If + the ready list at the idle priority contains more than one task + then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) + { + taskYIELD(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ + + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); + + /* Call the user defined function from within the idle task. This + allows the application designer to add background functionality + without the overhead of a separate task. + NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif /* configUSE_IDLE_HOOK */ + + /* This conditional compilation should use inequality to 0, not equality + to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + user defined low power mode implementations require + configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + TickType_t xExpectedIdleTime; + + /* It is not desirable to suspend then resume the scheduler on + each iteration of the idle task. Therefore, a preliminary + test of the expected idle time is performed without the + scheduler suspended. The result here is not necessarily + valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + vTaskSuspendAll(); + { + /* Now the scheduler is suspended, the expected idle + time can be sampled again, and this time its value can + be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICKLESS_IDLE */ + } +} +/*-----------------------------------------------------------*/ + +#if( configUSE_TICKLESS_IDLE != 0 ) + + eSleepModeStatus eTaskConfirmSleepModeStatus( void ) + { + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = 1; + eSleepModeStatus eReturn = eStandardSleep; + + if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) + { + /* A task was made ready while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else if( xYieldPending != pdFALSE ) + { + /* A yield was pended while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else + { + /* If all the tasks are in the suspended list (which might mean they + have an infinite block time rather than actually being suspended) + then it is safe to turn all clocks off and just wait for external + interrupts. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) + { + eReturn = eNoTasksWaitingTimeout; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return eReturn; + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) + { + TCB_t *pxTCB; + + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToSet ); + pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; + } + } + +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ +/*-----------------------------------------------------------*/ + +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + + void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) + { + void *pvReturn = NULL; + TCB_t *pxTCB; + + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + } + else + { + pvReturn = NULL; + } + + return pvReturn; + } + +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ +/*-----------------------------------------------------------*/ + +#if ( portUSING_MPU_WRAPPERS == 1 ) + + void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) + { + TCB_t *pxTCB; + + /* If null is passed in here then we are modifying the MPU settings of + the calling task. */ + pxTCB = prvGetTCBFromHandle( xTaskToModify ); + + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + } + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTaskLists( void ) +{ +UBaseType_t uxPriority; + + for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( &xDelayedTaskList1 ); + vListInitialise( &xDelayedTaskList2 ); + vListInitialise( &xPendingReadyList ); + + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( &xTasksWaitingTermination ); + } + #endif /* INCLUDE_vTaskDelete */ + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( &xSuspendedTaskList ); + } + #endif /* INCLUDE_vTaskSuspend */ + + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; +} +/*-----------------------------------------------------------*/ + +static void prvCheckTasksWaitingTermination( void ) +{ + + /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ + + #if ( INCLUDE_vTaskDelete == 1 ) + { + BaseType_t xListIsEmpty; + + /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called + too often in the idle task. */ + while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + { + vTaskSuspendAll(); + { + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + } + ( void ) xTaskResumeAll(); + + if( xListIsEmpty == pdFALSE ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(); + { + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + --uxCurrentNumberOfTasks; + --uxDeletedTasksWaitingCleanUp; + } + taskEXIT_CRITICAL(); + + prvDeleteTCB( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #endif /* INCLUDE_vTaskDelete */ +} +/*-----------------------------------------------------------*/ + +#if( configUSE_TRACE_FACILITY == 1 ) + + void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) + { + TCB_t *pxTCB; + + /* xTask is NULL then get the state of the calling task. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB; + pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] ); + pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority; + pxTaskStatus->pxStackBase = pxTCB->pxStack; + pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber; + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* If the task is in the suspended list then there is a chance it is + actually just blocked indefinitely - so really it should be reported as + being in the Blocked state. */ + if( pxTaskStatus->eCurrentState == eSuspended ) + { + vTaskSuspendAll(); + { + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + pxTaskStatus->eCurrentState = eBlocked; + } + } + xTaskResumeAll(); + } + } + #endif /* INCLUDE_vTaskSuspend */ + + #if ( configUSE_MUTEXES == 1 ) + { + pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; + } + #else + { + pxTaskStatus->uxBasePriority = 0; + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; + } + #else + { + pxTaskStatus->ulRunTimeCounter = 0; + } + #endif + + /* Obtaining the task state is a little fiddly, so is only done if the value + of eState passed into this function is eInvalid - otherwise the state is + just set to whatever is passed in. */ + if( eState != eInvalid ) + { + pxTaskStatus->eCurrentState = eState; + } + else + { + pxTaskStatus->eCurrentState = eTaskGetState( xTask ); + } + + /* Obtaining the stack space takes some time, so the xGetFreeStackSpace + parameter is provided to allow it to be skipped. */ + if( xGetFreeStackSpace != pdFALSE ) + { + #if ( portSTACK_GROWTH > 0 ) + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); + } + #else + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); + } + #endif + } + else + { + pxTaskStatus->usStackHighWaterMark = 0; + } + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) + { + volatile TCB_t *pxNextTCB, *pxFirstTCB; + UBaseType_t uxTask = 0; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + + /* Populate an TaskStatus_t structure within the + pxTaskStatusArray array for each task that is referenced from + pxList. See the definition of TaskStatus_t in task.h for the + meaning of each TaskStatus_t structure member. */ + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); + uxTask++; + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) + { + uint32_t ulCount = 0U; + + while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + ulCount++; + } + + ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ + + return ( uint16_t ) ulCount; + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + + UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + uint8_t *pucEndOfStack; + UBaseType_t uxReturn; + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } + #else + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } + #endif + + uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskGetStackHighWaterMark */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( TCB_t *pxTCB ) + { + /* This call is required specifically for the TriCore port. It must be + above the vPortFree() calls. The call is also used by ports/demos that + want to allocate and clean RAM statically. */ + portCLEAN_UP_TCB( pxTCB ); + + /* Free up the memory allocated by the scheduler for the task. It is up + to the task to free any memory allocated at the application level. */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) + { + /* The task can only have been allocated dynamically - free both + the stack and TCB. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 ) + { + /* The task could have been allocated statically or dynamically, so + check what was statically allocated before trying to free the + memory. */ + if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) + { + /* Both the stack and TCB were allocated dynamically, so both + must be freed. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + { + /* Only the stack was statically allocated, so the TCB is the + only memory that must be freed. */ + vPortFree( pxTCB ); + } + else + { + /* Neither the stack nor the TCB were allocated dynamically, so + nothing needs to be freed. */ + configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ) + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +static void prvResetNextTaskUnblockTime( void ) +{ +TCB_t *pxTCB; + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The new current delayed list is empty. Set xNextTaskUnblockTime to + the maximum possible value so it is extremely unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass until + there is an item in the delayed list. */ + xNextTaskUnblockTime = portMAX_DELAY; + } + else + { + /* The new current delayed list is not empty, get the value of + the item at the head of the delayed list. This is the time at + which the task at the head of the delayed list should be removed + from the Blocked state. */ + ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) + + TaskHandle_t xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + + /* A critical section is not required as this is not called from + an interrupt and the current TCB will always be the same for any + individual execution thread. */ + xReturn = pxCurrentTCB; + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + + BaseType_t xTaskGetSchedulerState( void ) + { + BaseType_t xReturn; + + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + + /* If the mutex was given back by an interrupt while the queue was + locked then the mutex holder might now be NULL. */ + if( pxMutexHolder != NULL ) + { + /* If the holder of the mutex has a priority below the priority of + the task attempting to obtain the mutex then it will temporarily + inherit the priority of the task attempting to obtain the mutex. */ + if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) + { + /* Adjust the mutex holder state to account for its new + priority. Only reset the event list item value if the value is + not being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* If the task being modified is in the ready state it will need + to be moved into a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Inherit the priority before being moved into the new list. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* Just inherit the priority. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + } + + traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + BaseType_t xReturn = pdFALSE; + + if( pxMutexHolder != NULL ) + { + /* A task can only have an inherited priority if it holds the mutex. + If the mutex is held by a task then it cannot be given from an + interrupt, and if a mutex is given by the holding task then it must + be the running state task. */ + configASSERT( pxTCB == pxCurrentTCB ); + + configASSERT( pxTCB->uxMutexesHeld ); + ( pxTCB->uxMutexesHeld )--; + + /* Has the holder of the mutex inherited the priority of another + task? */ + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* Only disinherit if no other mutexes are held. */ + if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + { + /* A task can only have an inherited priority if it holds + the mutex. If the mutex is held by a task then it cannot be + given from an interrupt, and if a mutex is given by the + holding task then it must be the running state task. Remove + the holding task from the ready list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Disinherit the priority before adding the task into the + new ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; + + /* Reset the event list item value. It cannot be in use for + any other purpose if this task is running, and it must be + running to give back the mutex. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + prvAddTaskToReadyList( pxTCB ); + + /* Return true to indicate that a context switch is required. + This is only actually required in the corner case whereby + multiple mutexes were held and the mutexes were given back + in an order different to that in which they were taken. + If a context switch did not occur when the first mutex was + returned, even if a task was waiting on it, then a context + switch should occur when the last mutex is returned whether + a task is waiting on it or not. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskEnterCritical( void ) + { + portDISABLE_INTERRUPTS(); + + if( xSchedulerRunning != pdFALSE ) + { + ( pxCurrentTCB->uxCriticalNesting )++; + + /* This is not the interrupt safe version of the enter critical + function so assert() if it is being called from an interrupt + context. Only API functions that end in "FromISR" can be used in an + interrupt. Only assert if the critical nesting count is 1 to + protect against recursive calls if the assert function also uses a + critical section. */ + if( pxCurrentTCB->uxCriticalNesting == 1 ) + { + portASSERT_IF_IN_ISR(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskExitCritical( void ) + { + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB->uxCriticalNesting > 0U ) + { + ( pxCurrentTCB->uxCriticalNesting )--; + + if( pxCurrentTCB->uxCriticalNesting == 0U ) + { + portENABLE_INTERRUPTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) + { + size_t x; + + /* Start by copying the entire string. */ + strcpy( pcBuffer, pcTaskName ); + + /* Pad the end of the string with spaces to ensure columns line up when + printed out. */ + for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) + { + pcBuffer[ x ] = ' '; + } + + /* Terminate. */ + pcBuffer[ x ] = 0x00; + + /* Return the new end of string. */ + return &( pcBuffer[ x ] ); + } + +#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + void vTaskList( char * pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + char cStatus; + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that + * displays task names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that + * might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, + * and limited functionality implementation of sprintf() is provided in + * many of the FreeRTOS/Demo sub-directories in a file called + * printf-stdarg.c (note printf-stdarg.c does not provide a full + * snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskList(). + */ + + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. NOTE! if + configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will + equate to NULL. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); + + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + switch( pxTaskStatusArray[ x ].eCurrentState ) + { + case eReady: cStatus = tskREADY_CHAR; + break; + + case eBlocked: cStatus = tskBLOCKED_CHAR; + break; + + case eSuspended: cStatus = tskSUSPENDED_CHAR; + break; + + case eDeleted: cStatus = tskDELETED_CHAR; + break; + + default: /* Should not get here, but it is included + to prevent static checking errors. */ + cStatus = 0x00; + break; + } + + /* Write the task name to the string, padding with spaces so it + can be printed in tabular form more easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + + /* Write the rest of the string. */ + sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); + pcWriteBuffer += strlen( pcWriteBuffer ); + } + + /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION + is 0 then vPortFree() will be #defined to nothing. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ +/*----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + void vTaskGetRunTimeStats( char *pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + uint32_t ulTotalTime, ulStatsAsPercentage; + + #if( configUSE_TRACE_FACILITY != 1 ) + { + #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). + } + #endif + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part + * of the uxTaskGetSystemState() output into a human readable table that + * displays the amount of time each task has spent in the Running state + * in both absolute and percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library + * function that might bloat the code size, use a lot of stack, and + * provide different results on different platforms. An alternative, + * tiny, third party, and limited functionality implementation of + * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in + * a file called printf-stdarg.c (note printf-stdarg.c does not provide + * a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskGetRunTimeStats(). + */ + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. NOTE! If + configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will + equate to NULL. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); + + /* For percentage calculations. */ + ulTotalTime /= 100UL; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > 0 ) + { + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + /* What percentage of the total run time has the task used? + This will always be rounded down to the nearest integer. + ulTotalRunTimeDiv100 has already been divided by 100. */ + ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; + + /* Write the task name to the string, padding with + spaces so it can be printed in tabular form more + easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + + if( ulStatsAsPercentage > 0UL ) + { + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); + } + #endif + } + else + { + /* If the percentage is zero here then the task has + consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #endif + } + + pcWriteBuffer += strlen( pcWriteBuffer ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION + is 0 then vPortFree() will be #defined to nothing. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ +/*-----------------------------------------------------------*/ + +TickType_t uxTaskResetEventItemValue( void ) +{ +TickType_t uxReturn; + + uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) ); + + /* Reset the event list item to its normal value - so it can be used with + queues and semaphores. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void *pvTaskIncrementMutexHeldCount( void ) + { + /* If xSemaphoreCreateMutex() is called before any tasks have been created + then pxCurrentTCB will be NULL. */ + if( pxCurrentTCB != NULL ) + { + ( pxCurrentTCB->uxMutexesHeld )++; + } + + return pxCurrentTCB; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) + { + uint32_t ulReturn; + + taskENTER_CRITICAL(); + { + /* Only block if the notification count is not already non-zero. */ + if( pxCurrentTCB->ulNotifiedValue == 0UL ) + { + /* Mark this task as waiting for a notification. */ + pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; + + if( xTicksToWait > ( TickType_t ) 0 ) + { + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + traceTASK_NOTIFY_TAKE_BLOCK(); + + /* All ports are written to allow a yield in a critical + section (some will yield immediately, others wait until the + critical section exits) - but it is not something that + application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + traceTASK_NOTIFY_TAKE(); + ulReturn = pxCurrentTCB->ulNotifiedValue; + + if( ulReturn != 0UL ) + { + if( xClearCountOnExit != pdFALSE ) + { + pxCurrentTCB->ulNotifiedValue = 0UL; + } + else + { + pxCurrentTCB->ulNotifiedValue = ulReturn - 1; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + } + taskEXIT_CRITICAL(); + + return ulReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + /* Only block if a notification is not already pending. */ + if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED ) + { + /* Clear bits in the task's notification value as bits may get + set by the notifying task or interrupt. This can be used to + clear the value to zero. */ + pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry; + + /* Mark this task as waiting for a notification. */ + pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; + + if( xTicksToWait > ( TickType_t ) 0 ) + { + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); + traceTASK_NOTIFY_WAIT_BLOCK(); + + /* All ports are written to allow a yield in a critical + section (some will yield immediately, others wait until the + critical section exits) - but it is not something that + application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + traceTASK_NOTIFY_WAIT(); + + if( pulNotificationValue != NULL ) + { + /* Output the current notification value, which may or may not + have changed. */ + *pulNotificationValue = pxCurrentTCB->ulNotifiedValue; + } + + /* If ucNotifyValue is set then either the task never entered the + blocked state (because a notification was already pending) or the + task unblocked because of a notification. Otherwise the task + unblocked because of a timeout. */ + if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION ) + { + /* A notification was not received. */ + xReturn = pdFALSE; + } + else + { + /* A notification was already pending or a notification was + received while the task was waiting. */ + pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit; + xReturn = pdTRUE; + } + + pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) + { + TCB_t * pxTCB; + BaseType_t xReturn = pdPASS; + uint8_t ucOriginalNotifyState; + + configASSERT( xTaskToNotify ); + pxTCB = ( TCB_t * ) xTaskToNotify; + + taskENTER_CRITICAL(); + { + if( pulPreviousNotificationValue != NULL ) + { + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + } + + ucOriginalNotifyState = pxTCB->ucNotifyState; + + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + + switch( eAction ) + { + case eSetBits : + pxTCB->ulNotifiedValue |= ulValue; + break; + + case eIncrement : + ( pxTCB->ulNotifiedValue )++; + break; + + case eSetValueWithOverwrite : + pxTCB->ulNotifiedValue = ulValue; + break; + + case eSetValueWithoutOverwrite : + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) + { + pxTCB->ulNotifiedValue = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } + break; + + case eNoAction: + /* The task is being notified without its notify value being + updated. */ + break; + } + + traceTASK_NOTIFY(); + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked waiting for a notification then + xNextTaskUnblockTime might be set to the blocked task's time + out time. If the task is unblocked for a reason other than + a timeout xNextTaskUnblockTime is normally left unchanged, + because it will automatically get reset to a new value when + the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter + sleep mode at the earliest possible time - so reset + xNextTaskUnblockTime here to ensure it is updated at the + earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + BaseType_t xReturn = pdPASS; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( xTaskToNotify ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + pxTCB = ( TCB_t * ) xTaskToNotify; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( pulPreviousNotificationValue != NULL ) + { + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + } + + ucOriginalNotifyState = pxTCB->ucNotifyState; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + + switch( eAction ) + { + case eSetBits : + pxTCB->ulNotifiedValue |= ulValue; + break; + + case eIncrement : + ( pxTCB->ulNotifiedValue )++; + break; + + case eSetValueWithOverwrite : + pxTCB->ulNotifiedValue = ulValue; + break; + + case eSetValueWithoutOverwrite : + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) + { + pxTCB->ulNotifiedValue = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } + break; + + case eNoAction : + /* The task is being notified without its notify value being + updated. */ + break; + } + + traceTASK_NOTIFY_FROM_ISR(); + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + /* Mark that a yield is pending in case the user is not + using the "xHigherPriorityTaskWoken" parameter to an ISR + safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( xTaskToNotify ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + pxTCB = ( TCB_t * ) xTaskToNotify; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + ucOriginalNotifyState = pxTCB->ucNotifyState; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + + /* 'Giving' is equivalent to incrementing a count in a counting + semaphore. */ + ( pxTCB->ulNotifiedValue )++; + + traceTASK_NOTIFY_GIVE_FROM_ISR(); + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + /* Mark that a yield is pending in case the user is not + using the "xHigherPriorityTaskWoken" parameter in an ISR + safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ + +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + BaseType_t xReturn; + + /* If null is passed in here then it is the calling task that is having + its notification state cleared. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + taskENTER_CRITICAL(); + { + if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) + { + pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + + +static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) +{ +TickType_t xTimeToWake; +const TickType_t xConstTickCount = xTickCount; + + #if( INCLUDE_xTaskAbortDelay == 1 ) + { + /* About to enter a delayed list, so ensure the ucDelayAborted flag is + reset to pdFALSE so it can be detected as having been set to pdTRUE + when the task leaves the Blocked state. */ + pxCurrentTCB->ucDelayAborted = pdFALSE; + } + #endif + + /* Remove the task from the ready list before adding it to the blocked list + as the same list item is used for both lists. */ + if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure it is not woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + kernel will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); + + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow + list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list + is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + + /* If the task entering the blocked state was placed at the + head of the list of blocked tasks then xNextTaskUnblockTime + needs to be updated too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the kernel + will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); + + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */ + ( void ) xCanBlockIndefinitely; + } + #endif /* INCLUDE_vTaskSuspend */ +} + + +#ifdef FREERTOS_MODULE_TEST + #include "tasks_test_access_functions.h" +#endif + diff --git a/STM32F1/libraries/FreeRTOS900/utility/timers.c b/STM32F1/libraries/FreeRTOS900/utility/timers.c new file mode 100644 index 0000000..d4a821a --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/timers.c @@ -0,0 +1,1092 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "timers.h" + +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. This #if is closed at the very bottom +of this file. If you want to include software timer functionality then ensure +configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#if ( configUSE_TIMERS == 1 ) + +/* Misc definitions. */ +#define tmrNO_DELAY ( TickType_t ) 0U + +/* The definition of the timers themselves. */ +typedef struct tmrTimerControl +{ + const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ + UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */ + void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ + #endif + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */ + #endif +} xTIMER; + +/* The old xTIMER name is maintained above then typedefed to the new Timer_t +name below to enable the use of older kernel aware debuggers. */ +typedef xTIMER Timer_t; + +/* The definition of messages that can be sent and received on the timer queue. +Two types of message can be queued - messages that manipulate a software timer, +and messages that request the execution of a non-timer related callback. The +two message types are defined in two separate structures, xTimerParametersType +and xCallbackParametersType respectively. */ +typedef struct tmrTimerParameters +{ + TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ +} TimerParameter_t; + + +typedef struct tmrCallbackParameters +{ + PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ + void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */ + uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ +} CallbackParameters_t; + +/* The structure that contains the two message types, along with an identifier +that is used to determine which message type is valid. */ +typedef struct tmrTimerQueueMessage +{ + BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ + union + { + TimerParameter_t xTimerParameters; + + /* Don't include xCallbackParameters if it is not going to be used as + it makes the structure (and therefore the timer queue) larger. */ + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + CallbackParameters_t xCallbackParameters; + #endif /* INCLUDE_xTimerPendFunctionCall */ + } u; +} DaemonTaskMessage_t; + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +/* The list in which active timers are stored. Timers are referenced in expire +time order, with the nearest expiry time at the front of the list. Only the +timer service task is allowed to access these lists. */ +PRIVILEGED_DATA static List_t xActiveTimerList1; +PRIVILEGED_DATA static List_t xActiveTimerList2; +PRIVILEGED_DATA static List_t *pxCurrentTimerList; +PRIVILEGED_DATA static List_t *pxOverflowTimerList; + +/* A queue that is used to send commands to the timer service task. */ +PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; +PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; + +/*lint +e956 */ + +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + /* If static allocation is supported then the application must provide the + following callback function - which enables the application to optionally + provide the memory that will be used by the timer task as the task's stack + and TCB. */ + extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ); + +#endif + +/* + * Initialise the infrastructure used by the timer service task if it has not + * been initialised already. + */ +static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; + +/* + * The timer service task (daemon). Timer functionality is controlled by this + * task. Other tasks communicate with the timer service task using the + * xTimerQueue queue. + */ +static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; + +/* + * Called by the timer service task to interpret and process a command it + * received on the timer queue. + */ +static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; + +/* + * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, + * depending on if the expire time causes a timer counter overflow. + */ +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; + +/* + * An active timer has reached its expire time. Reload the timer if it is an + * auto reload timer, then call its callback. + */ +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; + +/* + * The tick count has overflowed. Switch the timer lists after ensuring the + * current timer list does not still reference some timers. + */ +static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; + +/* + * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE + * if a tick count overflow occurred since prvSampleTimeNow() was last called. + */ +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; + +/* + * If the timer list contains any active timers then return the expire time of + * the timer that will expire first and set *pxListWasEmpty to false. If the + * timer list does not contain any timers then return 0 and set *pxListWasEmpty + * to pdTRUE. + */ +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; + +/* + * If a timer has expired, process it. Otherwise, block the timer service task + * until either a timer does expire or a command is received. + */ +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION; + +/* + * Called after a Timer_t structure has been allocated either statically or + * dynamically to fill in the structure's members. + */ +static void prvInitialiseNewTimer( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +/*-----------------------------------------------------------*/ + +BaseType_t xTimerCreateTimerTask( void ) +{ +BaseType_t xReturn = pdFAIL; + + /* This function is called when the scheduler is started if + configUSE_TIMERS is set to 1. Check that the infrastructure used by the + timer service task has been created/initialised. If timers have already + been created then the initialisation will already have been performed. */ + prvCheckForValidListAndQueue(); + + if( xTimerQueue != NULL ) + { + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + StaticTask_t *pxTimerTaskTCBBuffer = NULL; + StackType_t *pxTimerTaskStackBuffer = NULL; + uint32_t ulTimerTaskStackSize; + + vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize ); + xTimerTaskHandle = xTaskCreateStatic( prvTimerTask, + "Tmr Svc", + ulTimerTaskStackSize, + NULL, + ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, + pxTimerTaskStackBuffer, + pxTimerTaskTCBBuffer ); + + if( xTimerTaskHandle != NULL ) + { + xReturn = pdPASS; + } + } + #else + { + xReturn = xTaskCreate( prvTimerTask, + "Tmr Svc", + configTIMER_TASK_STACK_DEPTH, + NULL, + ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, + &xTimerTaskHandle ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + configASSERT( xReturn ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + TimerHandle_t xTimerCreate( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + Timer_t *pxNewTimer; + + pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); + + if( pxNewTimer != NULL ) + { + prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Timers can be created statically or dynamically, so note this + timer was created dynamically in case the timer is later + deleted. */ + pxNewTimer->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + } + + return pxNewTimer; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + Timer_t *pxNewTimer; + + #if( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + variable of type StaticTimer_t equals the size of the real timer + structures. */ + volatile size_t xSize = sizeof( StaticTimer_t ); + configASSERT( xSize == sizeof( Timer_t ) ); + } + #endif /* configASSERT_DEFINED */ + + /* A pointer to a StaticTimer_t structure MUST be provided, use it. */ + configASSERT( pxTimerBuffer ); + pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + + if( pxNewTimer != NULL ) + { + prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); + + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Timers can be created statically or dynamically so note this + timer was created statically in case it is later deleted. */ + pxNewTimer->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + } + + return pxNewTimer; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseNewTimer( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ + /* 0 is not a valid value for xTimerPeriodInTicks. */ + configASSERT( ( xTimerPeriodInTicks > 0 ) ); + + if( pxNewTimer != NULL ) + { + /* Ensure the infrastructure used by the timer service task has been + created/initialised. */ + prvCheckForValidListAndQueue(); + + /* Initialise the timer structure members using the function + parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->uxAutoReload = uxAutoReload; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + traceTIMER_CREATE( pxNewTimer ); + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) +{ +BaseType_t xReturn = pdFAIL; +DaemonTaskMessage_t xMessage; + + configASSERT( xTimer ); + + /* Send a message to the timer service task to perform a particular action + on a particular timer definition. */ + if( xTimerQueue != NULL ) + { + /* Send a command to the timer service task to start the xTimer timer. */ + xMessage.xMessageID = xCommandID; + xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; + xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer; + + if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) + { + if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + } + else + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); + } + } + else + { + xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + } + + traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) +{ + /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been + started, then xTimerTaskHandle will be NULL. */ + configASSERT( ( xTimerTaskHandle != NULL ) ); + return xTimerTaskHandle; +} +/*-----------------------------------------------------------*/ + +TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) +{ +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + configASSERT( xTimer ); + return pxTimer->xTimerPeriodInTicks; +} +/*-----------------------------------------------------------*/ + +TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) +{ +Timer_t * pxTimer = ( Timer_t * ) xTimer; +TickType_t xReturn; + + configASSERT( xTimer ); + xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + configASSERT( xTimer ); + return pxTimer->pcTimerName; +} +/*-----------------------------------------------------------*/ + +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) +{ +BaseType_t xResult; +Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list of active timers. A check has already + been performed to ensure the list is not empty. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* If the timer is an auto reload timer then calculate the next + expiry time and re-insert the timer in the list of active timers. */ + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + /* The timer is inserted into a list using a time relative to anything + other than the current time. It will therefore be inserted into the + correct list relative to the time this task thinks it is now. */ + if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE ) + { + /* The timer expired before it was added to the active timer + list. Reload it now. */ + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Call the timer callback. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); +} +/*-----------------------------------------------------------*/ + +static void prvTimerTask( void *pvParameters ) +{ +TickType_t xNextExpireTime; +BaseType_t xListWasEmpty; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) + { + extern void vApplicationDaemonTaskStartupHook( void ); + + /* Allow the application writer to execute some code in the context of + this task at the point the task starts executing. This is useful if the + application includes initialisation code that would benefit from + executing after the scheduler has been started. */ + vApplicationDaemonTaskStartupHook(); + } + #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ + + for( ;; ) + { + /* Query the timers list to see if it contains any timers, and if so, + obtain the time at which the next timer will expire. */ + xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); + + /* If a timer has expired, process it. Otherwise, block this task + until either a timer does expire, or a command is received. */ + prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); + + /* Empty the command queue. */ + prvProcessReceivedCommands(); + } +} +/*-----------------------------------------------------------*/ + +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) +{ +TickType_t xTimeNow; +BaseType_t xTimerListsWereSwitched; + + vTaskSuspendAll(); + { + /* Obtain the time now to make an assessment as to whether the timer + has expired or not. If obtaining the time causes the lists to switch + then don't process this timer as any timers that remained in the list + when the lists were switched will have been processed within the + prvSampleTimeNow() function. */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + if( xTimerListsWereSwitched == pdFALSE ) + { + /* The tick count has not overflowed, has the timer expired? */ + if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) + { + ( void ) xTaskResumeAll(); + prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); + } + else + { + /* The tick count has not overflowed, and the next expire + time has not been reached yet. This task should therefore + block to wait for the next expire time or a command to be + received - whichever comes first. The following line cannot + be reached unless xNextExpireTime > xTimeNow, except in the + case when the current timer list is empty. */ + if( xListWasEmpty != pdFALSE ) + { + /* The current timer list is empty - is the overflow list + also empty? */ + xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); + } + + vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); + + if( xTaskResumeAll() == pdFALSE ) + { + /* Yield to wait for either a command to arrive, or the + block time to expire. If a command arrived between the + critical section being exited and this yield then the yield + will not cause the task to block. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + ( void ) xTaskResumeAll(); + } + } +} +/*-----------------------------------------------------------*/ + +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) +{ +TickType_t xNextExpireTime; + + /* Timers are listed in expiry time order, with the head of the list + referencing the task that will expire first. Obtain the time at which + the timer with the nearest expiry time will expire. If there are no + active timers then just set the next expire time to 0. That will cause + this task to unblock when the tick count overflows, at which point the + timer lists will be switched and the next expiry time can be + re-assessed. */ + *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); + if( *pxListWasEmpty == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + } + else + { + /* Ensure the task unblocks when the tick count rolls over. */ + xNextExpireTime = ( TickType_t ) 0U; + } + + return xNextExpireTime; +} +/*-----------------------------------------------------------*/ + +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) +{ +TickType_t xTimeNow; +PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ + + xTimeNow = xTaskGetTickCount(); + + if( xTimeNow < xLastTime ) + { + prvSwitchTimerLists(); + *pxTimerListsWereSwitched = pdTRUE; + } + else + { + *pxTimerListsWereSwitched = pdFALSE; + } + + xLastTime = xTimeNow; + + return xTimeNow; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) +{ +BaseType_t xProcessTimerNow = pdFALSE; + + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + + if( xNextExpiryTime <= xTimeNow ) + { + /* Has the expiry time elapsed between the command to start/reset a + timer was issued, and the time the command was processed? */ + if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + { + /* The time between a command being issued and the command being + processed actually exceeds the timers period. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); + } + } + else + { + if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) + { + /* If, since the command was issued, the tick count has overflowed + but the expiry time has not, then the timer must have already passed + its expiry time and should be processed immediately. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + } + + return xProcessTimerNow; +} +/*-----------------------------------------------------------*/ + +static void prvProcessReceivedCommands( void ) +{ +DaemonTaskMessage_t xMessage; +Timer_t *pxTimer; +BaseType_t xTimerListsWereSwitched, xResult; +TickType_t xTimeNow; + + while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ + { + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + { + /* Negative commands are pended function calls rather than timer + commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) + { + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + + /* The timer uses the xCallbackParameters member to request a + callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); + + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* INCLUDE_xTimerPendFunctionCall */ + + /* Commands that are positive are timer commands rather than pended + function calls. */ + if( xMessage.xMessageID >= ( BaseType_t ) 0 ) + { + /* The messages uses the xTimerParameters member to work on a + software timer. */ + pxTimer = xMessage.u.xTimerParameters.pxTimer; + + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) + { + /* The timer is in a list, remove it. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); + + /* In this case the xTimerListsWereSwitched parameter is not used, but + it must be present in the function call. prvSampleTimeNow() must be + called after the message is received from xTimerQueue so there is no + possibility of a higher priority task adding a message to the message + queue with a time that is ahead of the timer daemon task (because it + pre-empted the timer daemon task after the xTimeNow value was set). */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + + switch( xMessage.xMessageID ) + { + case tmrCOMMAND_START : + case tmrCOMMAND_START_FROM_ISR : + case tmrCOMMAND_RESET : + case tmrCOMMAND_RESET_FROM_ISR : + case tmrCOMMAND_START_DONT_TRACE : + /* Start or restart a timer. */ + if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE ) + { + /* The timer expired before it was added to the active + timer list. Process it now. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + traceTIMER_EXPIRED( pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + break; + + case tmrCOMMAND_STOP : + case tmrCOMMAND_STOP_FROM_ISR : + /* The timer has already been removed from the active list. + There is nothing to do here. */ + break; + + case tmrCOMMAND_CHANGE_PERIOD : + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR : + pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; + configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); + + /* The new period does not really have a reference, and can + be longer or shorter than the old one. The command time is + therefore set to the current time, and as the period cannot + be zero the next expiry time can only be in the future, + meaning (unlike for the xTimerStart() case above) there is + no fail case that needs to be handled here. */ + ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); + break; + + case tmrCOMMAND_DELETE : + /* The timer has already been removed from the active list, + just free up the memory if the memory was dynamically + allocated. */ + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The timer can only have been allocated dynamically - + free it again. */ + vPortFree( pxTimer ); + } + #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The timer could have been allocated statically or + dynamically, so check before attempting to free the + memory. */ + if( pxTimer->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxTimer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + break; + + default : + /* Don't expect to get here. */ + break; + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSwitchTimerLists( void ) +{ +TickType_t xNextExpireTime, xReloadTime; +List_t *pxTemp; +Timer_t *pxTimer; +BaseType_t xResult; + + /* The tick count has overflowed. The timer lists must be switched. + If there are any timers still referenced from the current timer list + then they must have expired and should be processed before the lists + are switched. */ + while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list. */ + pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* Execute its callback, then send a command to restart the timer if + it is an auto-reload timer. It cannot be restarted here as the lists + have not yet been switched. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + /* Calculate the reload value, and if the reload value results in + the timer going into the same timer list then it has already expired + and the timer should be re-inserted into the current list so it is + processed again within this loop. Otherwise a command should be sent + to restart the timer to ensure it is only inserted into a list after + the lists have been swapped. */ + xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); + if( xReloadTime > xNextExpireTime ) + { + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + else + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxTemp = pxCurrentTimerList; + pxCurrentTimerList = pxOverflowTimerList; + pxOverflowTimerList = pxTemp; +} +/*-----------------------------------------------------------*/ + +static void prvCheckForValidListAndQueue( void ) +{ + /* Check that the list from which active timers are referenced, and the + queue used to communicate with the timer service, have been + initialised. */ + taskENTER_CRITICAL(); + { + if( xTimerQueue == NULL ) + { + vListInitialise( &xActiveTimerList1 ); + vListInitialise( &xActiveTimerList2 ); + pxCurrentTimerList = &xActiveTimerList1; + pxOverflowTimerList = &xActiveTimerList2; + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* The timer queue is allocated statically in case + configSUPPORT_DYNAMIC_ALLOCATION is 0. */ + static StaticQueue_t xStaticTimerQueue; + static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; + + xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); + } + #else + { + xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); + } + #endif + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + if( xTimerQueue != NULL ) + { + vQueueAddToRegistry( xTimerQueue, "TmrQ" ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configQUEUE_REGISTRY_SIZE */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) +{ +BaseType_t xTimerIsInActiveList; +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + configASSERT( xTimer ); + + /* Is the timer in the list of active timers? */ + taskENTER_CRITICAL(); + { + /* Checking to see if it is in the NULL list in effect checks to see if + it is referenced from either the current or the overflow timer lists in + one go, but the logic has to be reversed, hence the '!'. */ + xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); + } + taskEXIT_CRITICAL(); + + return xTimerIsInActiveList; +} /*lint !e818 Can't be pointer to const due to the typedef. */ +/*-----------------------------------------------------------*/ + +void *pvTimerGetTimerID( const TimerHandle_t xTimer ) +{ +Timer_t * const pxTimer = ( Timer_t * ) xTimer; +void *pvReturn; + + configASSERT( xTimer ); + + taskENTER_CRITICAL(); + { + pvReturn = pxTimer->pvTimerID; + } + taskEXIT_CRITICAL(); + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) +{ +Timer_t * const pxTimer = ( Timer_t * ) xTimer; + + configASSERT( xTimer ); + + taskENTER_CRITICAL(); + { + pxTimer->pvTimerID = pvNewID; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + + tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* This function can only be called after a timer has been created or + after the scheduler has been started because, until then, the timer + queue does not exist. */ + configASSERT( xTimerQueue ); + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + + tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. If you want to include software timer +functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#endif /* configUSE_TIMERS == 1 */ + + + diff --git a/STM32F1/libraries/FreeRTOS900/utility/timers.h b/STM32F1/libraries/FreeRTOS900/utility/timers.h new file mode 100644 index 0000000..798c955 --- /dev/null +++ b/STM32F1/libraries/FreeRTOS900/utility/timers.h @@ -0,0 +1,1314 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef TIMERS_H +#define TIMERS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include timers.h" +#endif + +/*lint -e537 This headers are only multiply included if the application code +happens to also be including task.h. */ +#include "task.h" +/*lint +e537 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +/* IDs for commands that can be sent/received on the timer queue. These are to +be used solely through the macros that make up the public software timer API, +as defined below. The commands that are sent from interrupts must use the +highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task +or interrupt version of the queue send function should be used. */ +#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) +#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) +#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) +#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) +#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) +#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) +#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) + +#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) +#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) +#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) + + +/** + * Type by which software timers are referenced. For example, a call to + * xTimerCreate() returns an TimerHandle_t variable that can then be used to + * reference the subject timer in calls to other software timer API functions + * (for example, xTimerStart(), xTimerReset(), etc.). + */ +typedef void * TimerHandle_t; + +/* + * Defines the prototype to which timer callback functions must conform. + */ +typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); + +/* + * Defines the prototype to which functions used with the + * xTimerPendFunctionCallFromISR() function must conform. + */ +typedef void (*PendedFunction_t)( void *, uint32_t ); + +/** + * TimerHandle_t xTimerCreate( const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, + * void * pvTimerID, + * TimerCallbackFunction_t pxCallbackFunction ); + * + * Creates a new software timer instance, and returns a handle by which the + * created software timer can be referenced. + * + * Internally, within the FreeRTOS implementation, software timers use a block + * of memory, in which the timer data structure is stored. If a software timer + * is created using xTimerCreate() then the required memory is automatically + * dynamically allocated inside the xTimerCreate() function. (see + * http://www.freertos.org/a00111.html). If a software timer is created using + * xTimerCreateStatic() then the application writer must provide the memory that + * will get used by the software timer. xTimerCreateStatic() therefore allows a + * software timer to be created without using any dynamic memory allocation. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a + * timer into the active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer + * by its handle, and never by its name. + * + * @param xTimerPeriodInTicks The timer period. The time is defined in tick + * periods so the constant portTICK_PERIOD_MS can be used to convert a time that + * has been specified in milliseconds. For example, if the timer must expire + * after 100 ticks, then xTimerPeriodInTicks should be set to 100. + * Alternatively, if the timer must expire after 500ms, then xPeriod can be set + * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or + * equal to 1000. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. + * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by TimerCallbackFunction_t, + * which is "void vCallbackFunction( TimerHandle_t xTimer );". + * + * @return If the timer is successfully created then a handle to the newly + * created timer is returned. If the timer cannot be created (because either + * there is insufficient FreeRTOS heap remaining to allocate the timer + * structures, or the timer period was set to 0) then NULL is returned. + * + * Example usage: + * @verbatim + * #define NUM_TIMERS 5 + * + * // An array to hold handles to the created timers. + * TimerHandle_t xTimers[ NUM_TIMERS ]; + * + * // An array to hold a count of the number of times each timer expires. + * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 }; + * + * // Define a callback function that will be used by multiple timer instances. + * // The callback function does nothing but count the number of times the + * // associated timer expires, and stop the timer once the timer has expired + * // 10 times. + * void vTimerCallback( TimerHandle_t pxTimer ) + * { + * int32_t lArrayIndex; + * const int32_t xMaxExpiryCountBeforeStopping = 10; + * + * // Optionally do something if the pxTimer parameter is NULL. + * configASSERT( pxTimer ); + * + * // Which timer expired? + * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); + * + * // Increment the number of times that pxTimer has expired. + * lExpireCounters[ lArrayIndex ] += 1; + * + * // If the timer has expired 10 times then stop it from running. + * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) + * { + * // Do not use a block time if calling a timer API function from a + * // timer callback function, as doing so could cause a deadlock! + * xTimerStop( pxTimer, 0 ); + * } + * } + * + * void main( void ) + * { + * int32_t x; + * + * // Create then start some timers. Starting the timers before the scheduler + * // has been started means the timers will start running immediately that + * // the scheduler starts. + * for( x = 0; x < NUM_TIMERS; x++ ) + * { + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * x ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. + * ); + * + * if( xTimers[ x ] == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * vTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + TimerHandle_t xTimerCreate( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/** + * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, + * void * pvTimerID, + * TimerCallbackFunction_t pxCallbackFunction, + * StaticTimer_t *pxTimerBuffer ); + * + * Creates a new software timer instance, and returns a handle by which the + * created software timer can be referenced. + * + * Internally, within the FreeRTOS implementation, software timers use a block + * of memory, in which the timer data structure is stored. If a software timer + * is created using xTimerCreate() then the required memory is automatically + * dynamically allocated inside the xTimerCreate() function. (see + * http://www.freertos.org/a00111.html). If a software timer is created using + * xTimerCreateStatic() then the application writer must provide the memory that + * will get used by the software timer. xTimerCreateStatic() therefore allows a + * software timer to be created without using any dynamic memory allocation. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a + * timer into the active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer + * by its handle, and never by its name. + * + * @param xTimerPeriodInTicks The timer period. The time is defined in tick + * periods so the constant portTICK_PERIOD_MS can be used to convert a time that + * has been specified in milliseconds. For example, if the timer must expire + * after 100 ticks, then xTimerPeriodInTicks should be set to 100. + * Alternatively, if the timer must expire after 500ms, then xPeriod can be set + * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or + * equal to 1000. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. + * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by TimerCallbackFunction_t, + * which is "void vCallbackFunction( TimerHandle_t xTimer );". + * + * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which + * will be then be used to hold the software timer's data structures, removing + * the need for the memory to be allocated dynamically. + * + * @return If the timer is created then a handle to the created timer is + * returned. If pxTimerBuffer was NULL then NULL is returned. + * + * Example usage: + * @verbatim + * + * // The buffer used to hold the software timer's data structure. + * static StaticTimer_t xTimerBuffer; + * + * // A variable that will be incremented by the software timer's callback + * // function. + * UBaseType_t uxVariableToIncrement = 0; + * + * // A software timer callback function that increments a variable passed to + * // it when the software timer was created. After the 5th increment the + * // callback function stops the software timer. + * static void prvTimerCallback( TimerHandle_t xExpiredTimer ) + * { + * UBaseType_t *puxVariableToIncrement; + * BaseType_t xReturned; + * + * // Obtain the address of the variable to increment from the timer ID. + * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer ); + * + * // Increment the variable to show the timer callback has executed. + * ( *puxVariableToIncrement )++; + * + * // If this callback has executed the required number of times, stop the + * // timer. + * if( *puxVariableToIncrement == 5 ) + * { + * // This is called from a timer callback so must not block. + * xTimerStop( xExpiredTimer, staticDONT_BLOCK ); + * } + * } + * + * + * void main( void ) + * { + * // Create the software time. xTimerCreateStatic() has an extra parameter + * // than the normal xTimerCreate() API function. The parameter is a pointer + * // to the StaticTimer_t structure that will hold the software timer + * // structure. If the parameter is passed as NULL then the structure will be + * // allocated dynamically, just as if xTimerCreate() had been called. + * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS. + * xTimerPeriod, // The period of the timer in ticks. + * pdTRUE, // This is an auto-reload timer. + * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function + * prvTimerCallback, // The function to execute when the timer expires. + * &xTimerBuffer ); // The buffer that will hold the software timer structure. + * + * // The scheduler has not started yet so a block time is not used. + * xReturned = xTimerStart( xTimer, 0 ); + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * vTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * void *pvTimerGetTimerID( TimerHandle_t xTimer ); + * + * Returns the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer, and by calling the + * vTimerSetTimerID() API function. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used as time specific (timer local) storage. + * + * @param xTimer The timer being queried. + * + * @return The ID assigned to the timer being queried. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** + * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); + * + * Sets the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used as time specific (timer local) storage. + * + * @param xTimer The timer being updated. + * + * @param pvNewID The ID to assign to the timer. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION; + +/** + * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); + * + * Queries a timer to see if it is active or dormant. + * + * A timer will be dormant if: + * 1) It has been created but not started, or + * 2) It is an expired one-shot timer that has not been restarted. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param xTimer The timer being queried. + * + * @return pdFALSE will be returned if the timer is dormant. A value other than + * pdFALSE will be returned if the timer is active. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. + * void vAFunction( TimerHandle_t xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is active, do something. + * } + * else + * { + * // xTimer is not active, do something else. + * } + * } + * @endverbatim + */ +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** + * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + * + * Simply returns the handle of the timer service/daemon task. It it not valid + * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; + +/** + * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStart() starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerStart() has equivalent functionality + * to the xTimerReset() API function. + * + * Starting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerStart() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerStart() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerStart() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() + * to be available. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the start command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStop() stops a timer that was previously started using either of the + * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), + * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. + * + * Stopping a timer ensures the timer is not in the active state. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() + * to be available. + * + * @param xTimer The handle of the timer being stopped. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the stop command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerChangePeriod() changes the period of a timer that was previously + * created using the xTimerCreate() API function. + * + * xTimerChangePeriod() can be called to change the period of an active or + * dormant state timer. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerChangePeriod() to be available. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the change period command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerChangePeriod() was called. xTicksToWait is ignored if + * xTimerChangePeriod() is called before the scheduler is started. + * + * @return pdFAIL will be returned if the change period command could not be + * sent to the timer command queue even after xTicksToWait ticks had passed. + * pdPASS will be returned if the command was successfully sent to the timer + * command queue. When the command is actually processed will depend on the + * priority of the timer service/daemon task relative to other tasks in the + * system. The timer service/daemon task priority is set by the + * configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. If the timer + * // referenced by xTimer is already active when it is called, then the timer + * // is deleted. If the timer referenced by xTimer is not active when it is + * // called, then the period of the timer is set to 500ms and the timer is + * // started. + * void vAFunction( TimerHandle_t xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is already active - delete it. + * xTimerDelete( xTimer ); + * } + * else + * { + * // xTimer is not active, change its period to 500ms. This will also + * // cause the timer to start. Block for a maximum of 100 ticks if the + * // change period command cannot immediately be sent to the timer + * // command queue. + * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS ) + * { + * // The command was successfully sent. + * } + * else + * { + * // The command could not be sent, even after waiting for 100 ticks + * // to pass. Take appropriate action here. + * } + * } + * } + * @endverbatim + */ + #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerDelete() deletes a timer that was previously created using the + * xTimerCreate() API function. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerDelete() to be available. + * + * @param xTimer The handle of the timer being deleted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the delete command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() + * is called before the scheduler is started. + * + * @return pdFAIL will be returned if the delete command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerChangePeriod() API function example usage scenario. + */ +#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerReset() re-starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerReset() will cause the timer to + * re-evaluate its expiry time so that it is relative to when xTimerReset() was + * called. If the timer was in the dormant state then xTimerReset() has + * equivalent functionality to the xTimerStart() API function. + * + * Resetting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerReset() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerReset() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerReset() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() + * to be available. + * + * @param xTimer The handle of the timer being reset/started/restarted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the reset command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer. + * + * TimerHandle_t xBacklightTimer = NULL; + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press event handler. + * void vKeyPressEventHandler( char cKey ) + * { + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. Wait 10 ticks for the command to be successfully sent + * // if it cannot be sent immediately. + * vSetBacklightState( BACKLIGHT_ON ); + * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * } + * + * void main( void ) + * { + * int32_t x; + * + * // Create then start the one-shot timer that is responsible for turning + * // the back-light off if no keys are pressed within a 5 second period. + * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. + * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks. + * pdFALSE, // The timer is a one-shot timer. + * 0, // The id is not used by the callback so can take any value. + * vBacklightTimerCallback // The callback function that switches the LCD back-light off. + * ); + * + * if( xBacklightTimer == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timer running as it has already + * // been set into the active state. + * vTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStart() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStartFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStartFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStartFromISR() function. If + * xTimerStartFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerStartFromISR() is actually called. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then restart the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The start command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStop() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being stopped. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStopFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStopFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStopFromISR() function. If + * xTimerStopFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the timer should be simply stopped. + * + * // The interrupt service routine that stops the timer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - simply stop the timer. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The stop command was not executed successfully. Take appropriate + * // action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerChangePeriod() that can be called from an interrupt + * service routine. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerChangePeriodFromISR() writes a message to the + * timer command queue, so has the potential to transition the timer service/ + * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() + * causes the timer service/daemon task to leave the Blocked state, and the + * timer service/daemon task has a priority equal to or greater than the + * currently executing task (the task that was interrupted), then + * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the + * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets + * this value to pdTRUE then a context switch should be performed before the + * interrupt exits. + * + * @return pdFAIL will be returned if the command to change the timers period + * could not be sent to the timer command queue. pdPASS will be returned if the + * command was successfully sent to the timer command queue. When the command + * is actually processed will depend on the priority of the timer service/daemon + * task relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the period of xTimer should be changed to 500ms. + * + * // The interrupt service routine that changes the period of xTimer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - change the period of xTimer to 500ms. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The command to change the timers period was not executed + * // successfully. Take appropriate action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerReset() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer that is to be started, reset, or + * restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerResetFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerResetFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerResetFromISR() function. If + * xTimerResetFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerResetFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + + +/** + * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * + * Used from application interrupt service routines to defer the execution of a + * function to the RTOS daemon task (the timer service task, hence this function + * is implemented in timers.c and is prefixed with 'Timer'). + * + * Ideally an interrupt service routine (ISR) is kept as short as possible, but + * sometimes an ISR either has a lot of processing to do, or needs to perform + * processing that is not deterministic. In these cases + * xTimerPendFunctionCallFromISR() can be used to defer processing of a function + * to the RTOS daemon task. + * + * A mechanism is provided that allows the interrupt to return directly to the + * task that will subsequently execute the pended callback function. This + * allows the callback function to execute contiguously in time with the + * interrupt - just as if the callback had executed in the interrupt itself. + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task (which is set using + * configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of + * the currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE within + * xTimerPendFunctionCallFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + * Example usage: + * @verbatim + * + * // The callback function that will execute in the context of the daemon task. + * // Note callback functions must all use this same prototype. + * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) + * { + * BaseType_t xInterfaceToService; + * + * // The interface that requires servicing is passed in the second + * // parameter. The first parameter is not used in this case. + * xInterfaceToService = ( BaseType_t ) ulParameter2; + * + * // ...Perform the processing here... + * } + * + * // An ISR that receives data packets from multiple interfaces + * void vAnISR( void ) + * { + * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; + * + * // Query the hardware to determine which interface needs processing. + * xInterfaceToService = prvCheckInterfaces(); + * + * // The actual processing is to be deferred to a task. Request the + * // vProcessInterface() callback function is executed, passing in the + * // number of the interface that needs processing. The interface to + * // service is passed in the second parameter. The first parameter is + * // not used in this case. + * xHigherPriorityTaskWoken = pdFALSE; + * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); + * + * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context + * // switch should be requested. The macro used is port specific and will + * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to + * // the documentation page for the port being used. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * + * } + * @endverbatim + */ +BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + + /** + * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * TickType_t xTicksToWait ); + * + * + * Used to defer the execution of a function to the RTOS daemon task (the timer + * service task, hence this function is implemented in timers.c and is prefixed + * with 'Timer'). + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param xTicksToWait Calling this function will result in a message being + * sent to the timer daemon task on a queue. xTicksToWait is the amount of + * time the calling task should remain in the Blocked state (so not using any + * processing time) for space to become available on the timer queue if the + * queue is found to be full. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + */ +BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * const char * const pcTimerGetName( TimerHandle_t xTimer ); + * + * Returns the name that was assigned to a timer when the timer was created. + * + * @param xTimer The handle of the timer being queried. + * + * @return The name assigned to the timer specified by the xTimer parameter. + */ +const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); + * + * Returns the period of a timer. + * + * @param xTimer The handle of the timer being queried. + * + * @return The period of the timer in ticks. + */ +TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** +* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); +* +* Returns the time in ticks at which the timer will expire. If this is less +* than the current tick count then the expiry time has overflowed from the +* current time. +* +* @param xTimer The handle of the timer being queried. +* +* @return If the timer is running then the time in ticks at which the timer +* will next expire is returned. If the timer is not running then the return +* value is undefined. +*/ +TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/* + * Functions beyond this part are not part of the public API and are intended + * for use by the kernel only. + */ +BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* TIMERS_H */ + + + diff --git a/STM32F1/libraries/OLED_I2C/OLED_I2C.h b/STM32F1/libraries/OLED_I2C/OLED_I2C.h index 4bde83f..abad639 100644 --- a/STM32F1/libraries/OLED_I2C/OLED_I2C.h +++ b/STM32F1/libraries/OLED_I2C/OLED_I2C.h @@ -87,7 +87,7 @@ */ #elif defined (__STM32F1__) #include "Arduino.h" -//#include +//#include #include "hardware/arm/HW_STM32_defines.h" #endif diff --git a/STM32F1/libraries/OLED_I2C/hardware/arm/HW_STM32.h b/STM32F1/libraries/OLED_I2C/hardware/arm/HW_STM32.h index 7060b44..20c1a16 100644 --- a/STM32F1/libraries/OLED_I2C/hardware/arm/HW_STM32.h +++ b/STM32F1/libraries/OLED_I2C/hardware/arm/HW_STM32.h @@ -1,7 +1,7 @@ -#include "HardWire.h" +#include "Wire.h" #define WIRE_WRITE HWIRE.write - HardWire HWIRE(2,I2C_FAST_MODE); // stupid compiler + TwoWire WIRE(2,I2C_FAST_MODE); // stupid compiler void OLED::_convert_float(char *buf, double num, int width, byte prec) { @@ -109,7 +109,7 @@ void OLED::update() twi->TWI_THR = scrbuf[b]; while ((twi->TWI_SR & TWI_SR_TXRDY) != TWI_SR_TXRDY) {}; */ - static byte aa=scrbuf[b]; + byte aa=scrbuf[b]; WIRE_WRITE(aa); } diff --git a/STM32F1/libraries/RTClock/examples/BluePill-RTClock-test/BluePill-RTClock-test.ino b/STM32F1/libraries/RTClock/examples/BluePill-RTClock-test/BluePill-RTClock-test.ino new file mode 100644 index 0000000..cc78ec5 --- /dev/null +++ b/STM32F1/libraries/RTClock/examples/BluePill-RTClock-test/BluePill-RTClock-test.ino @@ -0,0 +1,169 @@ +/* STM32F103C8 Blue Pill ( PC13) + + Serialport set and display RTC clock , Write by CSNOL https://github.com/csnol/STM32-Examples + based on https://github.com/rogerclarkmelbourne/Arduino_STM32 + + 1. Blink on PC13 per 4s or 7s by attachAlarmInterrupt for 10 times + 2. Second counter by attachSecondsInterrupt + 3. Serial output on(41s) or off(21s) by creatAlarm + 4. change to your timezone in the sketch; + 3. get Unix epoch time from https://www.epochconverter.com/ ; + 4. last step input the 10 digit number( example: 1503945555) to Serialport ; + 5. the clock will be reset to you wanted. + + ## Why the 10 digit Unix epoch time be used? +****Because I wanna connect to NTP server by ESP-8266. +****in the library. getNtpTime() will return this 10 digit Unix epoch time. +* +* å—¨ï¼æœ‹å‹ä»¬ï¼Œ 这是一个STM32F10x系列的RTC应用的例å­ï¼Œå¸Œæœ›å¯¹ä½ çš„ç¼–ç æœ‰æ‰€å¸®åŠ© +* 这个程åºåŸºäºŽhttps://github.com/rogerclarkmelbourne/Arduino_STM32 , 感谢所有贡献者的付出。 +* 程åºæµ‹è¯•äº† F10x系列RTC çš„ 几ç§ä¸­æ–­ï¼Œ 并通过LED和串å£è¿›è¡Œè¡¨è¾¾ã€‚ +* RTClock 使用 UTC 作为时间标准, ä½ å¯ä»¥ä»Žhttps://www.epochconverter.com/ 获得 Unix epoch time数值 +* 并通过串å£è¿›è¡Œè®¾ç½®ï¼Œ 当然你也å¯ä»¥ç•¥å¾®ä¿®æ”¹ä¸€ä¸‹ä¸²å£æŽ¥æ”¶å¤„ç†æ–¹æ³•ï¼Œç›´æŽ¥ä»Žä¸²å£æŽ¥æ”¶æ—¥æœŸå½¢å¼ã€‚如 2017-9-13-10:30:00, +* å¦å¤–一个方法是通过ESP8266获å–NTP网络时间,并定期å‘é€ç»™F10x进行更新。 +*/ + + +#include + +RTClock rtclock (RTCSEL_LSE); // initialise +int timezone = 8; // change to your timezone +time_t tt, tt1; +tm_t mtt; +uint8_t dateread[11]; +int globAlmCount = 0; +int lastGlobAlmCount; +int SPECAlmCount = 0; +int lastSPECAlmCount; +int alarmcount = 3; +uint8_t AlarmExchange = 0; +bool dispflag = true; + +//----------------------------------------------------------------------------- +const char * weekdays[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; +const char * months[] = {"Dummy", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +//----------------------------------------------------------------------------- +uint8_t str2month(const char * d) +{ + uint8_t i = 13; + while ( (--i) && strcmp(months[i], d)!=0 ); + return i; +} +//----------------------------------------------------------------------------- +const char * delim = " :"; +char s[128]; // for sprintf +//----------------------------------------------------------------------------- +void ParseBuildTimestamp(tm_t & mt) +{ + // Timestamp format: "Dec 8 2017, 22:57:54" + sprintf(s, "Timestamp: %s, %s\n", __DATE__, __TIME__); + //Serial.print(s); + char * token = strtok(s, delim); // get first token + // walk through tokens + while( token != NULL ) { + uint8_t m = str2month((const char*)token); + if ( m>0 ) { + mt.month = m; + //Serial.print(" month: "); Serial.println(mt.month); + token = strtok(NULL, delim); // get next token + mt.day = atoi(token); + //Serial.print(" day: "); Serial.println(mt.day); + token = strtok(NULL, delim); // get next token + mt.year = atoi(token) - 1970; + //Serial.print(" year: "); Serial.println(mt.year); + token = strtok(NULL, delim); // get next token + mt.hour = atoi(token); + //Serial.print(" hour: "); Serial.println(mt.hour); + token = strtok(NULL, delim); // get next token + mt.minute = atoi(token); + //Serial.print(" minute: "); Serial.println(mt.minute); + token = strtok(NULL, delim); // get next token + mt.second = atoi(token); + //Serial.print(" second: "); Serial.println(mt.second); + } + token = strtok(NULL, delim); + } +} +//----------------------------------------------------------------------------- +// This function is called in the attachSecondsInterrupt +//----------------------------------------------------------------------------- +void SecondCount () +{ + tt++; +} +//----------------------------------------------------------------------------- +// This function is called in the attachAlarmInterrupt +//----------------------------------------------------------------------------- +void blink () +{ + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + globAlmCount++; +} +//----------------------------------------------------------------------------- +void OnOffSerial () +{ + dispflag = !dispflag; + SPECAlmCount++; +} +//----------------------------------------------------------------------------- +void setup() +{ + lastGlobAlmCount = ~globAlmCount; + lastSPECAlmCount = ~SPECAlmCount; + Serial.begin(115200); + pinMode(LED_BUILTIN, OUTPUT); + //while (!Serial); delay(1000); + ParseBuildTimestamp(mtt); // get the Unix epoch Time counted from 00:00:00 1 Jan 1970 + tt = rtclock.makeTime(mtt) + 25; // additional seconds to compensate build and upload delay + rtclock.setTime(tt); + tt1 = tt; + rtclock.attachAlarmInterrupt(blink);// Call blink + rtclock.attachSecondsInterrupt(SecondCount);// Call SecondCount +} +//----------------------------------------------------------------------------- +void loop() +{ + if ( Serial.available()>10 ) { + for (uint8_t i = 0; i<11; i++) { + dateread[i] = Serial.read(); + } + Serial.flush(); + tt = atol((char*)dateread); + rtclock.setTime(rtclock.TimeZone(tt, timezone)); //adjust to your local date + } + if (lastGlobAlmCount != globAlmCount || lastSPECAlmCount != SPECAlmCount ) { + if (globAlmCount == 10) { // to detachAlarmInterrupt and start creatAlarm after 10 times about 110s + rtclock.detachAlarmInterrupt(); + globAlmCount = 0; + rtclock.createAlarm(OnOffSerial, (rtclock.getTime() + 20)); // call OnOffSerial stop output date from Serial after 2 mins + alarmcount = 20; //change to creatAlarm 21S close Serial output and 41s open Serial output. + } + else { + lastGlobAlmCount = globAlmCount; + lastSPECAlmCount = SPECAlmCount; + Serial.println(" Say hello to every guys "); + if(dispflag == false) + Serial.println(" SPECAlarm turn Display Off "); + switch (AlarmExchange) { + case 0: + rtclock.setAlarmTime(rtclock.getTime() + alarmcount); // reset alarm = current time + 4s for attachAlarmInterrupt, 21s for creatAlarm + AlarmExchange = 1; + break; + case 1: + rtclock.breakTime(rtclock.getTime() + alarmcount * 2, mtt); //// reset alarm = current time + 7s for attachAlarmInterrupt, 41s for creatAlarm + rtclock.setAlarmTime(mtt); + AlarmExchange = 0; + break; + } + } + } + if (tt1 != tt && dispflag == true ) + { + tt1 = tt; + // get and print actual RTC timestamp + rtclock.breakTime(rtclock.now(), mtt); + sprintf(s, "RTC timestamp: %s %u %u, %s, %02u:%02u:%02u\n", + months[mtt.month], mtt.day, mtt.year+1970, weekdays[mtt.weekday], mtt.hour, mtt.minute, mtt.second); + Serial.print(s); + } +} diff --git a/STM32F1/libraries/RTClock/keywords.txt b/STM32F1/libraries/RTClock/keywords.txt index ddd0680..7e9a60d 100644 --- a/STM32F1/libraries/RTClock/keywords.txt +++ b/STM32F1/libraries/RTClock/keywords.txt @@ -5,16 +5,36 @@ ####################################### # Datatypes (KEYWORD1) ####################################### -RTClock KEYWORD1 + +RTClock KEYWORD1 -setTime KEYWORD2 -getTime KEYWORD2 +setTime KEYWORD2 +getTime KEYWORD2 + +createAlarm KEYWORD2 +removeAlarm KEYWORD2 +setAlarmTime KEYWORD2 -createAlarm KEYWORD2 attachSecondsInterrupt KEYWORD2 detachSecondsInterrupt KEYWORD2 -setAlarmTime KEYWORD2 + +attachAlarmInterrupt KEYWORD2 +detachAlarmInterrupt KEYWORD2 + +breakTime KEYWORD2 +makeTime KEYWORD2 + +TimeZone KEYWORD2 +now KEYWORD2 +year KEYWORD2 +month KEYWORD2 +day KEYWORD2 +weekday KEYWORD2 +hour KEYWORD2 +minute KEYWORD2 +second KEYWORD2 +isPM KEYWORD2 ####################################### diff --git a/STM32F1/libraries/RTClock/src/RTClock.cpp b/STM32F1/libraries/RTClock/src/RTClock.cpp old mode 100644 new mode 100755 index 869e152..8d65c1c --- a/STM32F1/libraries/RTClock/src/RTClock.cpp +++ b/STM32F1/libraries/RTClock/src/RTClock.cpp @@ -39,7 +39,7 @@ }//end RTC - RTClock::RTClock(rtc_clk_src src, uint16 prescaler ) { + RTClock::RTClock(rtc_clk_src src, uint32 prescaler ) { switch (src) { case RTCSEL_LSE : { @@ -80,22 +80,113 @@ } */ + void RTClock::setTime (tm_t & tmm) { + time_t mktm = makeTime(tmm); // time will be make to mktm + setTime(mktm); + //rtc_set_count(time_stamp); + } + void RTClock::setTime (time_t time_stamp) { rtc_set_count(time_stamp); } - void RTClock::setTime (struct tm* tm_ptr) { - rtc_set_count(mktime (tm_ptr)); - } +#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) + //----------------------------------------------------------------------------- +void RTClock::breakTime(time_t timeInput, tm_t & tmm) +{ +// break the given time_t into time components +// this is a more compact version of the C library localtime function +// note that year is offset from 1970 !!! + + uint8_t year; + uint8_t month, monthLength; + uint32_t time; + uint32_t days; + + time = (uint32_t)timeInput; + tmm.second = time % 60; + time /= 60; // now it is minutes + tmm.minute = time % 60; + time /= 60; // now it is hours + tmm.hour = time % 24; + time /= 24; // now it is days + tmm.weekday = ((time + 3) % 7); // Monday is day 1 + + year = 0; + days = 0; + while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { + year++; + } + tmm.year = year; // year is offset from 1970 + + days -= LEAP_YEAR(year) ? 366 : 365; + time -= days; // now it is days in this year, starting at 0 + + days = 0; + month = 0; + monthLength = 0; + for (month=0; month<12; month++) { + if (month==1) { // february + if (LEAP_YEAR(year)) { + monthLength=29; + } else { + monthLength=28; + } + } else { + monthLength = monthDays[month]; + } + + if (time >= monthLength) { + time -= monthLength; + } else { + break; + } + } + tmm.month = month + 1; // jan is month 1 + tmm.day = time + 1; // day of month +} + +//----------------------------------------------------------------------------- +time_t RTClock::makeTime(tm_t & tmm) +{ +// assemble time elements into time_t +// note year argument is offset from 1970 (see macros in time.h to convert to other formats) +// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 + + int i; + uint32_t seconds; + + // seconds from 1970 till 1 jan 00:00:00 of the given year + seconds = tmm.year*(SECS_PER_DAY * 365); + for (i = 0; i < tmm.year; i++) { + if (LEAP_YEAR(i)) { + seconds += SECS_PER_DAY; // add extra days for leap years + } + } + + // add days for this year, months start from 1 + for (i = 1; i < tmm.month; i++) { + if ( (i == 2) && LEAP_YEAR(tmm.year)) { + seconds += SECS_PER_DAY * 29; + } else { + seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 + } + } + seconds+= (tmm.day-1) * SECS_PER_DAY; + seconds+= tmm.hour * SECS_PER_HOUR; + seconds+= tmm.minute * SECS_PER_MIN; + seconds+= tmm.second; + return (time_t)seconds; +} + time_t RTClock::getTime() { return rtc_get_count(); } - - struct tm* RTClock::getTime(struct tm* tm_ptr) { + + void RTClock::getTime(tm_t & tm_ptr) { time_t res = rtc_get_count(); - tm_ptr = gmtime(&res); //why not gmtime? - return tm_ptr; + breakTime(res, tm_ptr); } void RTClock::createAlarm(voidFuncPtr function, time_t alarm_time_t) { @@ -103,6 +194,10 @@ rtc_attach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT, function); } + void RTClock::removeAlarm() { + rtc_detach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT); + } + void RTClock::attachSecondsInterrupt(voidFuncPtr function) { rtc_attach_interrupt(RTC_SECONDS_INTERRUPT, function); } @@ -110,15 +205,28 @@ rtc_detach_interrupt(RTC_SECONDS_INTERRUPT); } + void RTClock::attachAlarmInterrupt(voidFuncPtr function, time_t alarm_time) { // Don't need run RTClock::setAlarmTime(time_t alarm_time) + rtc_set_alarm(alarm_time); + rtc_attach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT, function); + } - void RTClock::createAlarm(voidFuncPtr function, tm* alarm_tm) { - time_t alarm = mktime(alarm_tm);//convert to time_t + void RTClock::attachAlarmInterrupt(voidFuncPtr function) { // Must run RTClock::setAlarmTime (time_t alarm_time or tm_t & alarm_tm) first + rtc_attach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT, function); + } + + void RTClock::detachAlarmInterrupt() { + rtc_detach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT); + } + + void RTClock::createAlarm(voidFuncPtr function, tm_t & alarm_tm) { + time_t alarm = makeTime(alarm_tm);//convert to time_t createAlarm(function, alarm); } //change alarm time - void RTClock::setAlarmTime (tm * tm_ptr) { - time_t time = mktime(tm_ptr);//convert to time_t + + void RTClock::setAlarmTime (tm_t & tm_ptr) { + time_t time = makeTime(tm_ptr);//convert to time_t rtc_set_alarm(time); //must be int... for standardization sake. } diff --git a/STM32F1/libraries/RTClock/src/RTClock.h b/STM32F1/libraries/RTClock/src/RTClock.h old mode 100644 new mode 100755 index 443a30b..7e758db --- a/STM32F1/libraries/RTClock/src/RTClock.h +++ b/STM32F1/libraries/RTClock/src/RTClock.h @@ -7,37 +7,99 @@ #ifndef _RTCLOCK_H_ #define _RTCLOCK_H_ +#define SECS_PER_MIN (60UL) +#define SECS_PER_HOUR (3600UL) +#define SECS_PER_DAY (SECS_PER_HOUR * 24UL) +#define DAYS_PER_WEEK (7UL) +#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK) +#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL) +#define SECS_YR_2000 (946684800UL) // the time at the start of y2k +#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) +#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc + #warning "Using private time_t definintion" + typedef uint32_t time_t; +#endif +static const unsigned char monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 +typedef struct tm_t { + uint8_t year; // years since 1970 + uint8_t month; // month of a year - [ 1 to 12 ] + uint8_t day; // day of a month - [ 1 to 31 ] + uint8_t weekday; // day of a week (first day is Monday) - [ 0 to 6 ] + uint8_t pm; // AM: 0, PM: 1 + uint8_t hour; // hour of a day - [ 0 to 23 ] + uint8_t minute; // minute of an hour - [ 0 to 59 ] + uint8_t second; // second of a minute - [ 0 to 59 ] +} tm_t; + +static inline uint8_t bcd2bin(uint8_t b) { return ( (10*(b>>4)) + (b&0x0F) ); } +static inline uint8_t bin2bcd(uint8_t b) { return ( ((b/10)<<4) + (b%10) ); } class RTClock { public: RTClock(); RTClock(rtc_clk_src src ); - RTClock(rtc_clk_src src, uint16 prescaler ); + RTClock(rtc_clk_src src, uint32 prescaler ); //~RTClock(); //to implement - - void setTime (time_t time_stamp); - void setTime (struct tm * tm_ptr); + void breakTime(time_t epoch_time, tm_t & tmm); + time_t makeTime(tm_t & tmm); + + void setTime (time_t time_stamp); + void setTime (tm_t & tmm); - struct tm* getTime(struct tm* tm_ptr); time_t getTime(); + void getTime(tm_t & tmm ); + + time_t now() { return getTime(); } + void now(tm_t & tmm ) { getTime(tmm); } // non-standard use of now() function, added for compatibility with previous versions of the library + + uint8_t year(void) { getTime(tmm); return tmm.year; } + uint8_t month(void) { getTime(tmm); return tmm.month; } + uint8_t day(void) { getTime(tmm); return tmm.day; } + uint8_t weekday(void) { getTime(tmm); return tmm.weekday; } + uint8_t hour(void) { getTime(tmm); return tmm.hour; } + uint8_t minute(void) { getTime(tmm); return tmm.minute; } + uint8_t second(void) { getTime(tmm); return tmm.second; } + uint8_t isPM(void) { return ( hour()>=12 ); } + + uint8_t year(time_t t) { breakTime(t, tmm); return tmm.year; } + uint8_t month(time_t t) { breakTime(t, tmm); return tmm.month; } + uint8_t day(time_t t) { breakTime(t, tmm); return tmm.day; } + uint8_t weekday(time_t t) { breakTime(t, tmm); return tmm.weekday; } + uint8_t hour(time_t t) { breakTime(t, tmm); return tmm.hour; } + uint8_t minute(time_t t) { breakTime(t, tmm); return tmm.minute; } + uint8_t second(time_t t) { breakTime(t, tmm); return tmm.second; } + uint8_t isPM(time_t t) { return (hour(t)>=12); } + + // Usage: localtime = TimeZone(UnixTime, 8); + time_t TimeZone(time_t t, int TZ) { return ( t + (TZ * SECS_PER_HOUR)); } + + // Usage: 1. localtime = TimeZone(UnixTime, 9, 45) -> UTC +09:45 TimeZone; + time_t TimeZone(time_t t, int HTZ, int MTZ) { return ( t + (HTZ * SECS_PER_HOUR) + (MTZ * 60)); } // HTZ = Hour offset, MTZ = Minute offset void createAlarm(voidFuncPtr function, time_t alarm_time_t); - void createAlarm(voidFuncPtr function, struct tm* alarm_tm); + void createAlarm(voidFuncPtr function, struct tm_t & alarm_tm); + void removeAlarm(); void attachSecondsInterrupt(voidFuncPtr function); void detachSecondsInterrupt(); - void setAlarmTime (tm * tm_ptr); + void attachAlarmInterrupt(voidFuncPtr function); + void attachAlarmInterrupt(voidFuncPtr function, time_t alarm_time); + void detachAlarmInterrupt(); + + void setAlarmTime (tm_t & tm_ptr); void setAlarmTime (time_t alarm_time); - //private: + + + tm_t tmm; +}; -} ; #endif // _RTCLOCK_H_ - \ No newline at end of file + diff --git a/STM32F1/libraries/RTClock/src/utility/rtc_util.c b/STM32F1/libraries/RTClock/src/utility/rtc_util.c index 3c8b7d5..3d7a262 100644 --- a/STM32F1/libraries/RTClock/src/utility/rtc_util.c +++ b/STM32F1/libraries/RTClock/src/utility/rtc_util.c @@ -168,8 +168,10 @@ uint32 rtc_get_count() { rtc_clear_sync(); rtc_wait_sync(); rtc_wait_finished(); - h = RTC->regs->CNTH & 0xffff; - l = RTC->regs->CNTL & 0xffff; + do { + h = RTC->regs->CNTH & 0xffff; + l = RTC->regs->CNTL & 0xffff; + } while (h != (RTC->regs->CNTH & 0xffff)); return (h << 16) | l; } @@ -211,8 +213,10 @@ uint32 rtc_get_divider() { rtc_clear_sync(); rtc_wait_sync(); rtc_wait_finished(); - h = RTC->regs->DIVH & 0x000f; - l = RTC->regs->DIVL & 0xffff; + do { + h = RTC->regs->DIVH & 0x000f; + l = RTC->regs->DIVL & 0xffff; + } while (h != (RTC->regs->DIVH & 0x000f)); return (h << 16) | l; } @@ -229,4 +233,4 @@ void rtc_set_alarm(uint32 value) { RTC->regs->ALRL = value & 0xffff; rtc_exit_config_mode(); rtc_wait_finished(); -} \ No newline at end of file +} diff --git a/STM32F1/libraries/RTClock/src/utility/rtc_util.h b/STM32F1/libraries/RTClock/src/utility/rtc_util.h index 7084b0d..5432de3 100644 --- a/STM32F1/libraries/RTClock/src/utility/rtc_util.h +++ b/STM32F1/libraries/RTClock/src/utility/rtc_util.h @@ -52,16 +52,16 @@ extern "C" { #endif typedef struct rtc_reg_map { - __io uint32 CRH; /**< Control register high */ - __io uint32 CRL; /**< Control register high */ - __io uint32 PRLH; /**< Prescaler load register high */ - __io uint32 PRLL; /**< Prescaler load register low */ - __io uint32 DIVH; /**< Prescaler divider register high */ - __io uint32 DIVL; /**< Prescaler divider register low */ - __io uint32 CNTH; /**< Counter register high */ - __io uint32 CNTL; /**< Counter register low */ - __io uint32 ALRH; /**< Alarm register high */ - __io uint32 ALRL; /**< Alarm register low */ + __IO uint32 CRH; /**< Control register high */ + __IO uint32 CRL; /**< Control register high */ + __IO uint32 PRLH; /**< Prescaler load register high */ + __IO uint32 PRLL; /**< Prescaler load register low */ + __IO uint32 DIVH; /**< Prescaler divider register high */ + __IO uint32 DIVL; /**< Prescaler divider register low */ + __IO uint32 CNTH; /**< Counter register high */ + __IO uint32 CNTL; /**< Counter register low */ + __IO uint32 ALRH; /**< Alarm register high */ + __IO uint32 ALRL; /**< Alarm register low */ } rtc_reg_map; /** RTC register map base pointer */ diff --git a/STM32F1/libraries/SDIO/SdioF1.cpp b/STM32F1/libraries/SDIO/SdioF1.cpp new file mode 100644 index 0000000..e8a15f9 --- /dev/null +++ b/STM32F1/libraries/SDIO/SdioF1.cpp @@ -0,0 +1,1307 @@ +/* Arduino SdCard Library + * Copyright (C) 2016 by William Greiman + * + * This file is part of the Arduino SdSpiCard Library + * + * This Library 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 3 of the License, or + * (at your option) any later version. + * + * This Library 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 the Arduino SdSpiCard Library. If not, see + * . + */ + +#include "SdioF1.h" +#include +#include +#include + + +#define USE_DEBUG_MODE 0 +#define USE_YIELD 0 + +//============================================================================== +//#define SDHC_PROCTL_DTW_4BIT 0x01 +#define CMD8_RETRIES 10 +#define BUSY_TIMEOUT_MILLIS 1000 +//============================================================================== +#define CMD_RESP_NONE SDIO_CMD_WAIT_NO_RESP +#define CMD_RESP_R1 SDIO_CMD_WAIT_SHORT_RESP // normal response +#define CMD_RESP_R1b SDIO_CMD_WAIT_SHORT_RESP // normal response + busy data line (optional) +#define CMD_RESP_R2 SDIO_CMD_WAIT_LONG_RESP // CID, CSD +#define CMD_RESP_R3 SDIO_CMD_WAIT_SHORT_RESP // OCR register, response to ACMD41 +#define CMD_RESP_R6 SDIO_CMD_WAIT_SHORT_RESP // published RCA response, response to CMD3 +#define CMD_RESP_R7 SDIO_CMD_WAIT_SHORT_RESP // response to CMD8 + +#define CMD0_XFERTYP (uint16_t)( CMD0 | CMD_RESP_NONE ) +#define CMD2_XFERTYP (uint16_t)( CMD2 | CMD_RESP_R2 ) +#define CMD3_XFERTYP (uint16_t)( CMD3 | CMD_RESP_R6 ) +#define CMD6_XFERTYP (uint16_t)( CMD6 | CMD_RESP_R1 ) +#define ACMD6_XFERTYP (uint16_t)( ACMD6 | CMD_RESP_R1 ) +#define CMD7_XFERTYP (uint16_t)( CMD7 | CMD_RESP_R1b ) +#define CMD8_XFERTYP (uint16_t)( CMD8 | CMD_RESP_R7 ) +#define CMD9_XFERTYP (uint16_t)( CMD9 | CMD_RESP_R2 ) +#define CMD10_XFERTYP (uint16_t)( CMD10 | CMD_RESP_R2 ) +#define CMD12_XFERTYP (uint16_t)( CMD12 | CMD_RESP_R1b ) +#define CMD13_XFERTYP (uint16_t)( CMD13 | CMD_RESP_R1 ) +#define CMD17_XFERTYP (uint16_t)( CMD17 | CMD_RESP_R1 ) +#define CMD18_XFERTYP (uint16_t)( CMD18 | CMD_RESP_R1 ) +#define ACMD23_XFERTYP (uint16_t)( ACMD23 | CMD_RESP_R1 ) +#define CMD24_XFERTYP (uint16_t)( CMD24 | CMD_RESP_R1 ) +#define CMD25_XFERTYP (uint16_t)( CMD25 | CMD_RESP_R1 ) +#define CMD32_XFERTYP (uint16_t)( CMD32 | CMD_RESP_R1 ) +#define CMD33_XFERTYP (uint16_t)( CMD32 | CMD_RESP_R1 ) +#define CMD38_XFERTYP (uint16_t)( CMD38 | CMD_RESP_R1b ) +#define ACMD41_XFERTYP (uint16_t)( ACMD41 | CMD_RESP_R3 ) + +/* + * ACMD42 to enable disable CD/D3 pull up. Needed for 4bit mode. + */ +const uint8_t ACMD42 = 0X2A; +#define ACMD42_XFERTYP (uint16_t)( ACMD41 | CMD_RESP_R1 ) + +#define CMD55_XFERTYP (uint16_t)( CMD55 | CMD_RESP_R1 ) + +//============================================================================= +//static void enableGPIO(bool enable); +//static void enableDmaIrs(); +static void initSDHC(void); +static bool isBusyCMD13(void); +static bool isBusyTransferComplete(void); +static bool isBusyTransferCRC(void); +//static bool isBusyCommandComplete(); +//static bool isBusyCommandInhibit(); +static bool readReg16(uint32_t xfertyp, void* data); +//static void setSdclk(uint32_t kHzMax); +static bool yieldTimeout(bool (*fcn)(void)); +static bool yieldDmaStatus(void); +static bool waitDmaStatus(void); +static bool waitTimeout(bool (*fcn)(void)); +//----------------------------------------------------------------------------- +static const uint32_t IDLE_STATE = 0; +static const uint32_t READ_STATE = 1; +static const uint32_t WRITE_STATE = 2; +volatile uint32_t m_curLba; +volatile uint32_t m_limitLba; +volatile uint8_t m_curState; +volatile uint64_t m_totalReadLbas = 0; +volatile uint64_t m_readErrors = 0; +volatile uint64_t m_writeErrors = 0; +volatile uint64_t m_totalWriteLbas = 0; + +#define TRX_RD 0 +#define TRX_WR 1 +static uint8_t m_dir = TRX_RD; +static bool (*m_busyFcn)() = 0; +static bool m_initDone = false; +//static uint32_t m_lba; // for raw non-DMA read(write)Start, read(write)Data, read(write)Stop +static uint32_t m_cnt; // for raw non-DMA read(write)Start, read(write)Data, read(write)Stop +static bool m_version2; +static bool m_highCapacity; +static uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED; +static uint32_t m_errorLine = 0; +static uint32_t m_rca; +//static volatile bool m_dmaBusy = false; +static volatile uint32_t m_irqstat; +static uint32_t m_sdClkKhz = 0; +static uint32_t m_ocr; +static cid_t m_cid; +static csd_t m_csd; +static uint32_t t = 0; + +uint32_t aligned[128]; // temporary buffer for misaligned buffers +//============================================================================= + +#if USE_DEBUG_MODE +#define DBG_PRINT() { \ + Serial.write('_'); Serial.print(__FUNCTION__); Serial.write('_'); Serial.print(__LINE__); Serial.print(": "); \ + Serial.print("DMA->ISR: 0x"); Serial.print(SDIO_DMA_DEV->regs->ISR, HEX); \ + /*Serial.print("DMA->HISR: "); Serial.println(SDIO_DMA_DEV->regs->HISR, HEX);*/ \ + Serial.print(", DMA->CCR: 0x"); Serial.print(SDIO_DMA_DEV->regs->CCR4, HEX); \ + Serial.print(", DMA->CNDTR: "); Serial.print(SDIO_DMA_DEV->regs->CNDTR4,DEC); \ + /**/Serial.print(", DMA->CPAR: 0x"); Serial.print(SDIO_DMA_DEV->regs->CPAR4, HEX); \ + /**/Serial.print(", DMA->CMAR: 0x"); Serial.print(SDIO_DMA_DEV->regs->CMAR4, HEX); \ + Serial.print(", DMA->IFCR: 0x"); Serial.print(SDIO_DMA_DEV->regs->IFCR, HEX); \ + \ + /*Serial.print(" SDIO->POWER: "); Serial.println(SDIO->POWER, HEX);*/ \ + Serial.print(", SDIO->CLKCR: 0x"); Serial.print(SDIO->CLKCR, HEX); \ + Serial.print(", SDIO->DTIMER: 0x"); Serial.print(SDIO->DTIMER, HEX); \ + Serial.print(", SDIO->DCTRL: 0x"); Serial.print(SDIO->DCTRL, HEX); \ + /**/Serial.print(", SDIO->DLEN: "); Serial.print(SDIO->DLEN); \ + Serial.print(", SDIO->DCOUNT: "); Serial.print(SDIO->DCOUNT); \ + Serial.print(", SDIO->STA: 0x"); Serial.println(SDIO->STA, HEX); \ + Serial.print(", SDIO->FIFOCNT: "); Serial.println(SDIO->FIFOCNT); \ + /*delay(1);*/ \ +} +#define DBG_PIN PD0 + +#else // USE_DEBUG_MODE +#define DBG_PRINT() +#endif // USE_DEBUG_MODE + +/*****************************************************************************/ +static void _panic(const char *message, uint32_t code) +{ + Serial.print(message); Serial.println(code, HEX); + //Block the execution with blinky leds + while (1) {delay (1);}; +/* + pinMode(BOARD_LED_PIN, OUTPUT); + //pinMode(BOARD_LED2_PIN, OUTPUT); + while (1) { + digitalWrite(BOARD_LED_PIN, HIGH); + //digitalWrite(BOARD_LED2_PIN, LOW); + delay(250); + digitalWrite(BOARD_LED_PIN, LOW); + //digitalWrite(BOARD_LED2_PIN, HIGH); + delay(250); + } + */ +} +/*===========================================================================*/ +/* + * Todo: Change the DMA parts so it works with F1 DMA, but since yield is disabled, we can ignore it for now. +*/ + +#if USE_YIELD +void yield(void) +{ + uint32_t val = SDIO->STA; + if ( val & SDIO_STA_TRX_ERROR_FLAGS ) { + Serial.print("SDIO ERROR:: SDIO->CLKCR: "); Serial.print(SDIO->CLKCR, HEX); \ + Serial.print(", SDIO->DTIMER: "); Serial.print(SDIO->DTIMER, HEX); \ + Serial.print(", SDIO->DCTRL: "); Serial.print(SDIO->DCTRL, HEX); \ + Serial.print(", SDIO->DLEN: "); Serial.print(SDIO->DLEN); \ + Serial.print(", SDIO->DCOUNT: "); Serial.print(SDIO->DCOUNT); \ + Serial.print(", SDIO->STA: "); Serial.print(SDIO->STA, HEX); \ + Serial.print(", SDIO->RESP0: "); Serial.println(SDIO->RESP[0], HEX); \ + if (val & SDIO_STA_STBITERR) Serial.print(" STBITERR"); + if (val & SDIO_STA_RXOVERR) Serial.print(" RXOVERR"); + if (val & SDIO_STA_TXUNDERR) Serial.print(" TXUNDERR"); + if (val & SDIO_STA_DTIMEOUT) Serial.print(" DTIMEOUT"); + if (val & SDIO_STA_DCRCFAIL) Serial.print(" DCRCFAIL"); + _panic(" - SDIO: Data Transmission Error ", val); + } + + val = dma_get_isr_bits(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); +/* if ( val & DMA_ISR_FEIF ) { + val ^= DMA_ISR_FEIF; + dma_clear_isr_bits(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + } +*/ + if ( val ) { + if (val & DMA_ISR_TEIF) Serial.print(" TEIF"); + //if (val & DMA_ISR_DMEIF) Serial.print(" DMEIF"); + //if (val & DMA_ISR_FEIF) Serial.print(" FEIF"); + _panic(" - DMA: Data Transmission Error ", val); + } + //Serial.write('.'); +} +#endif +//============================================================================= +// Error function and macro. +inline bool setSdErrorCode(uint8_t code, uint32_t line) { + m_errorCode = code; + m_errorLine = line; + return false; // setSdErrorCode +} +#define sdError(code) setSdErrorCode(code, __LINE__) +//============================================================================= +/* ISR +void sdhc_isr() { + SDHC_IRQSIGEN = 0; + m_irqstat = SDHC_IRQSTAT; + SDHC_IRQSTAT = m_irqstat; + m_dmaBusy = false; +}*/ +//============================================================================= +// Static functions. +//----------------------------------------------------------------------------- +static bool cardCommand(uint16_t xfertyp, uint32_t arg) +{ +#if USE_DEBUG_MODE==2 + Serial.print("cardCommand: "); Serial.print(xfertyp&SDIO_CMD_CMDINDEX); Serial.print(", arg: "); Serial.print(arg, HEX); +#endif + uint8_t resp = sdio_cmd_send(xfertyp, arg); // returns non-zero if OK, zero if it fails +#if USE_DEBUG_MODE==2 + Serial.print(", resp: "); Serial.print(resp, HEX); + Serial.print(", SDIO->STA: "); Serial.print(SDIO->STA, HEX); Serial.print(", cmd_resp: "); Serial.print(SDIO->RESP[0], HEX); + if ( (xfertyp&SDIO_CMD_WAIT_LONG_RESP)==SDIO_CMD_WAIT_LONG_RESP ) { + Serial.print(", "); Serial.print(SDIO->RESP[1], HEX); Serial.print(", "); Serial.print(SDIO->RESP[2], HEX); Serial.print(", "); Serial.println(SDIO->RESP[3], HEX); + } else Serial.println(); +#endif + return resp; // return non-zero when OK +} +//----------------------------------------------------------------------------- +static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) { + return cardCommand(CMD55_XFERTYP, rca) && cardCommand((uint16_t)xfertyp, arg); +} +/*---------------------------------------------------------------------------*/ +static bool cardCMD6(uint32_t arg, uint8_t* status) { + // CMD6 returns 64 bytes. + // use polling only for the moment + if (waitTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + // get the 64 bytes over data lines + sdio_setup_transfer(80000, 64, (SDIO_BLOCKSIZE_64 | SDIO_DIR_RX | SDIO_DCTRL_DTEN)); + + cardCommand(CMD6_XFERTYP, arg); + + // wait data Rx response + if (waitTimeout(isBusyTransferComplete)) { + return sdError(SD_CARD_ERROR_CMD6); + } +DBG_PRINT(); + // copy 64 bytes as 16 words from FIFO to buffer + for (uint8_t i=0; i<16; i++) { + *(uint32_t*)(&status[i<<2]) = SDIO->FIFO; + } + //SDIO->DCTRL = 0; // disable data controller + +#if USE_DEBUG_MODE + Serial.print("read data: "); for (uint8_t i=0; i<17; i++) { Serial.print(status[i], HEX); Serial.print(", "); } Serial.println(); +#endif +return true; +} +//----------------------------------------------------------------------------- +static void initSDHC(void) +{ + sdio_begin(); + DBG_PRINT(); +} +/*---------------------------------------------------------------------------*/ +static bool isBusyCMD13(void) { + if (!cardCommand(CMD13_XFERTYP, m_rca)) { // SEND_STATUS + // Caller will timeout. + return true; + } + return !(SDIO->RESP[0] & CARD_STATUS_READY_FOR_DATA); +} + +/* + * Returns False if DMA transfer disabled. + * True otherwise + */ +static bool inline isEnabledDMA(void) +{ + return dma_is_enabled(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); +} + +/* + * Returns False if DMA transfer is completed or in error. + * True otherwise + */ +static bool isBusyDMA(void) +{ + if (!isEnabledDMA()) return false; + uint8_t isr = dma_get_isr_bits(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + isr &= DMA_ISR_TCIF | DMA_ISR_TEIF; + //if (isr&DMA_ISR_TCIF) dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return !(isr); // ignore transfer error flag +} + +/*---------------------------------------------------------------------------*/ +/* + * Returns true while the transfer has not completed + * False when it has completed. + */ +static bool isBusyTransferComplete(void) +{ + uint32_t mask = SDIO->STA &(SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS); +//#if USE_DEBUG_MODE + if ( mask & SDIO_STA_TRX_ERROR_FLAGS ) { + Serial.print("XFER ERROR: SDIO->STA: "); Serial.print(SDIO->STA, HEX); + if (mask & SDIO_STA_STBITERR) Serial.print(" STBITERR"); + if (mask & SDIO_STA_RXOVERR) Serial.print(" RXOVERR"); + if (mask & SDIO_STA_TXUNDERR) Serial.print(" TXUNDERR"); + if (mask & SDIO_STA_DTIMEOUT) Serial.print(" DTIMEOUT"); + if (mask & SDIO_STA_DCRCFAIL) Serial.print(" DCRCFAIL"); + Serial.println(); + } +//#endif + if (mask) { + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return false; + } + return true; +} + + +/* + * New function, to follow Reference Manual sequence. + * Returns true if still not confirmed DBCKEND: Data block sent/received (CRC check passed) + * False when it has completed the transfer with CRC check. + */ +static bool isBusyTransferCRC(void) +{ + uint32_t mask = SDIO->STA &(SDIO_STA_DBCKEND | SDIO_STA_TRX_ERROR_FLAGS); +#if USE_DEBUG_MODE + if ( mask & SDIO_STA_TRX_ERROR_FLAGS ) { + Serial.print("XFER ERROR: SDIO->STA: "); Serial.print(SDIO->STA, HEX); + if (mask & SDIO_STA_STBITERR) Serial.print(" STBITERR"); + if (mask & SDIO_STA_RXOVERR) Serial.print(" RXOVERR"); + if (mask & SDIO_STA_TXUNDERR) Serial.print(" TXUNDERR"); + if (mask & SDIO_STA_DTIMEOUT) Serial.print(" DTIMEOUT"); + if (mask & SDIO_STA_DCRCFAIL) Serial.print(" DCRCFAIL"); + Serial.println(); + } +#endif + if (mask) { + //dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + //Serial.print("SDIO->STA SDIO_STA_DBCKEND"); Serial.println(SDIO->STA && SDIO_STA_DBCKEND, HEX); + return false; + } + return true; +} + + +/*---------------------------------------------------------------------------*/ +static void trxStart(uint8_t* buf, uint32_t n, uint8_t dir) +{ + m_dir = dir; + uint32_t flags = (SDIO_BLOCKSIZE_512 | SDIO_DCTRL_DTEN); + if (dir==TRX_RD) flags |= SDIO_DIR_RX; + // setup SDIO to transfer n blocks of 512 bytes + sdio_setup_transfer(0x00FFFFFF, n, flags); +} +/*---------------------------------------------------------------------------*/ +static bool trxStop() +{ + if (!cardCommand(CMD12_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD12); + } + /* + * Added this to wait to complete on sync. + */ + if (yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + if ( t ) { + Serial.print(", in "); Serial.println(millis()-t); + t = 0; + } + return true; +} +/*---------------------------------------------------------------------------*/ +static bool dmaTrxStart(uint32_t n, uint8_t dir) +{ + uint32_t flags = (SDIO_BLOCKSIZE_512 | SDIO_DCTRL_DMAEN | SDIO_DCTRL_DTEN); + if (dir==TRX_RD) flags |= SDIO_DIR_RX; + // setup SDIO to transfer n blocks of 512 bytes + sdio_setup_transfer(0x00FFFFFF, n, flags); + + return true; +} + +/* + * This one replaces dmaTrxStart, and will just prepare the DMA part, then a new + * one will enable the DMA reception as per the RM. + */ +static bool dmaTrxPrepare(uint8_t* buf, uint32_t n, uint8_t dir) +{ + uint32_t flags; + m_dir = dir; + if ((3 & (uint32_t)buf) || n == 0) { // check alignment + _panic("- transferStart: unaligned buffer address ", (uint32_t)buf); + return sdError(SD_CARD_ERROR_DMA); + } + /* + * No point to wait here again if we always wait before calling this. + if (dir==TRX_RD && yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + */ + + /* + * Following RM 22.3.2. Setup DMA first, SDIO peripheral next + * + */ + flags = (DMA_MINC_MODE); + // not extra flag if read + if (dir!=TRX_RD) flags |= DMA_FROM_MEM;// write + dma_setup_transfer(SDIO_DMA_DEV, SDIO_DMA_CHANNEL, &SDIO->FIFO, DMA_SIZE_32BITS, buf, DMA_SIZE_32BITS, flags); + dma_set_num_transfers(SDIO_DMA_DEV, SDIO_DMA_CHANNEL, n>>2); // F1 DMA controller counts each word as 1 data item. + //dma_set_fifo_flags(SDIO_DMA_DEV, SDIO_DMA_CHANNEL, (DMA_FCR_DMDIS | DMA_FCR_FTH_FULL)); // disable direct mode | threshold FULL + dma_clear_isr_bits(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + dma_enable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + + return true; +} + + +/*---------------------------------------------------------------------------*/ +static bool dmaTrxEnd(bool multi_block) +{ + if(m_curState != READ_STATE){ + if ( yieldTimeout(isBusyTransferComplete) ) { + DBG_PRINT(); + if (m_dir==TRX_RD) + return sdError(SD_CARD_ERROR_READ_CRC); + else + return sdError(SD_CARD_ERROR_WRITE); + } + } + + if ( !yieldDmaStatus() ) { + DBG_PRINT(); + return sdError(SD_CARD_ERROR_DMA); + } + + if (multi_block) { + return trxStop(); + } else { + if ( t ) { + Serial.print(", in "); Serial.println(millis()-t); + t = 0; + } + return true; + } +} +//----------------------------------------------------------------------------- +// Read 16 byte CID or CSD register. +static bool readReg16(uint32_t xfertyp, void* data) +{ + // It's not safe to call this function if a multiblock read/write is going on. + if (m_curState != IDLE_STATE) { + return false; + } + uint8_t* d = reinterpret_cast(data); + if (!cardCommand(xfertyp, m_rca)) { + return false; // Caller will set errorCode. + } + *(uint32_t*)(&d[0]) = __builtin_bswap32(SDIO->RESP[0]); + *(uint32_t*)(&d[4]) = __builtin_bswap32(SDIO->RESP[1]); + *(uint32_t*)(&d[8]) = __builtin_bswap32(SDIO->RESP[2]); + *(uint32_t*)(&d[12]) = __builtin_bswap32(SDIO->RESP[3]); + d[15] = 0; + return true; +} +/*---------------------------------------------------------------------------*/ +// Return true if timeout occurs. +static bool yieldTimeout(bool (*fcn)()) { + m_busyFcn = fcn; + uint32_t m = millis(); + while (fcn()) { + if ((millis() - m) > BUSY_TIMEOUT_MILLIS) { + m_busyFcn = 0; + return true; + } + yield(); + } + m_busyFcn = 0; + return false; // Caller will set errorCode. +} +/*---------------------------------------------------------------------------*/ +static bool yieldDmaStatus(void) +{ + if (yieldTimeout(isBusyDMA)) { + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return false; // Caller will set errorCode. + } + // Did not time out. Disable it and return true. + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return true; +} +/*---------------------------------------------------------------------------*/ +static bool waitDmaStatus(void) +{ + if (waitTimeout(isBusyDMA)) { + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return false; // Caller will set errorCode. + } + // Did not time out. Disable it and return true + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return true; +} +/*---------------------------------------------------------------------------*/ +// Return true if timeout occurs. +static bool waitTimeout(bool (*fcn)(void)) { + uint32_t m = millis(); + while (fcn()) { + if ((millis() - m) > BUSY_TIMEOUT_MILLIS) { + return true; + } + delayMicroseconds(1); + } + return false; // Caller will set errorCode. +} + + +//============================================================================= +bool SdioCard::begin(void) +{ + + uint32_t arg; + m_initDone = false; + m_errorCode = SD_CARD_ERROR_NONE; + m_highCapacity = false; + m_version2 = false; + +#if USE_DEBUG_MODE +pinMode(DBG_PIN, OUTPUT); +digitalWrite(DBG_PIN, HIGH); +delay(100); +#endif + // initialize controller. + initSDHC(); + + // initialize DMA device + dma_init(SDIO_DMA_DEV); + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); // Disable DMA in case it was left enabled from a previous use. + /* + * Todo. Check this, channel must be disabled to change DMA priority, and seems like channel is not completing transfers + */ + dma_set_priority(SDIO_DMA_DEV, SDIO_DMA_CHANNEL, DMA_PRIORITY_VERY_HIGH); + + if (!cardCommand(CMD0_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD0); + } + delay(50); //small pause after reset command + // Try several times for case of reset delay. + for (uint32_t i = 0; i < CMD8_RETRIES; i++) { + if (cardCommand(CMD8_XFERTYP, 0X1AA)) { + if (SDIO->RESP[0] != 0X1AA) { + return sdError(SD_CARD_ERROR_CMD8); + } + m_version2 = true; + break; + } + } + arg = m_version2 ? 0X50300000 : 0x00300000; + uint32_t m = millis(); + do { + if (!cardAcmd(0, ACMD41_XFERTYP, arg) || + ((millis() - m) > BUSY_TIMEOUT_MILLIS)) { + return sdError(SD_CARD_ERROR_ACMD41); + } + } while ((SDIO->RESP[0] & 0x80000000) == 0); + + m_ocr = SDIO->RESP[0]; + if (m_ocr & 0x40000000) { + // Is high capacity. + m_highCapacity = true; + } + if (!cardCommand(CMD2_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD2); + } + if (!cardCommand(CMD3_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD3); + } + m_rca = SDIO->RESP[0] & 0xFFFF0000; + + if (!readReg16(CMD9_XFERTYP, &m_csd)) { + return sdError(SD_CARD_ERROR_CMD9); + } + if (!readReg16(CMD10_XFERTYP, &m_cid)) { + return sdError(SD_CARD_ERROR_CMD10); + } + if (!cardCommand(CMD7_XFERTYP, m_rca)) { + return sdError(SD_CARD_ERROR_CMD7); + } + + arg = 0x00; //bit 0, Connect[1]/Disconnect[0] the 50 KOhm pull-up resistor on CD/DAT3 + if (!cardAcmd(m_rca, ACMD42_XFERTYP, arg)) { + _panic("*** ACMD42 to disconnect D3 pullup failed! ***", 0); + } + + // Set card to bus width four. + if (!cardAcmd(m_rca, ACMD6_XFERTYP, 2)) { + return sdError(SD_CARD_ERROR_ACMD6); + } + + // Set SDHC to bus width four. + sdio_set_dbus_width(SDIO_CLKCR_WIDBUS_4BIT); + +/* + // Determine if High Speed mode is supported and set frequency. + uint8_t status[64]; + // see "Physical Layer Simplified Specification Version 6.00", chapter 4.3.10, Table 4-13. + // Support Bits of Functions in Function Group 1: bits 415:400, which are bytes [12][13] + // Function Selection of Function Group 1: bits 379:376, which is low nibble of byte [16] + if (cardCMD6(0X00FFFFFF, status) && (2 & status[13]) && + cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) { + Serial.println("\n*** 50MHz clock supported ***"); + m_sdClkKhz = 24000; // set clock to 24MHz + } else { + //_panic("*** Only 25MHz clock supported! ***", 0); + m_sdClkKhz = 8000; // set clock to 24MHz + } + */ + // delay seems to be needed for cards that take some time to adjust */ + delay(1); + + m_sdClkKhz = 18000; // set clock to 24MHz + sdio_set_clock(m_sdClkKhz*1000); + + m_initDone = true; + return true; +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::cardSize(void) { + return sdCardCapacity(&m_csd); +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::erase(uint32_t firstBlock, uint32_t lastBlock) { + // check for single block erase + if (!m_csd.v1.erase_blk_en) { + // erase size mask + uint8_t m = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low; + if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { + // error card can't erase specified area + return sdError(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + } + } + if (!m_highCapacity) { + firstBlock <<= 9; + lastBlock <<= 9; + } + if (!cardCommand(CMD32_XFERTYP, firstBlock)) { + return sdError(SD_CARD_ERROR_CMD32); + } + if (!cardCommand(CMD33_XFERTYP, lastBlock)) { + return sdError(SD_CARD_ERROR_CMD33); + } + if (!cardCommand(CMD38_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD38); + } + if (waitTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_ERASE_TIMEOUT); + } + return true; +} +//----------------------------------------------------------------------------- +uint8_t SdioCard::errorCode() { + return m_errorCode; +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::errorData() { + return m_irqstat; +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::errorLine() { + return m_errorLine; +} +//----------------------------------------------------------------------------- +bool SdioCard::isBusy() { + return m_busyFcn ? m_busyFcn() : m_initDone && isBusyCMD13(); +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::kHzSdClk() { + return m_sdClkKhz; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readBlock(uint32_t lba, uint8_t* buf) +{ +#if USE_DEBUG_MODE + Serial.print("readBlock: "); Serial.println(lba); //Serial.print(", buf: "); Serial.println((uint32_t)buf, HEX); +#endif + volatile bool _state = false; + uint16_t retries = 3; + while ( retries-- ){ + /*if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + */ + + if (m_curState != READ_STATE || m_curLba != lba) { +#if USE_DEBUG_MODE + Serial.print("New lba, syncing :"); + Serial.println(lba); +#endif + _state = syncBlocks(); + DBG_PRINT(); + if (!_state) { + return false; + } + m_limitLba = (lba + 1024); //arbitrary limit, tested with 32KB before and worked fine. + // prepare DMA for data read transfer + _state = dmaTrxPrepare((uint32_t)buf & 3 ? (uint8_t*)aligned : buf, 512, TRX_RD); + DBG_PRINT(); + + // prepare SDIO data read transfer 0x8000 = 64*512 + _state = dmaTrxStart(512, TRX_RD); + DBG_PRINT(); + + // send command to start data transfer + _state = cardCommand(CMD18_XFERTYP, (m_highCapacity ? lba : 512*lba)); + DBG_PRINT(); + if ( !_state ) { + return sdError(SD_CARD_ERROR_CMD18); + } + + m_curLba = lba; + m_curState = READ_STATE; + } + else { + // prepare DMA for data read transfer + _state = dmaTrxPrepare((uint32_t)buf & 3 ? (uint8_t*)aligned : buf, 512, TRX_RD); + + // prepare SDIO data read transfer + _state = dmaTrxStart(512, TRX_RD); + } + + + _state = dmaTrxEnd(0); + + if ( _state ) { + if ( (uint32_t)buf & 3 ) { + //memcpy(buf, aligned, 512); + register uint8_t * dst = buf; + register uint8_t * src = (uint8_t *)aligned; + register uint16_t i = 64; + while ( i-- ) { // do 8 byte copies, is much faster than single byte copy + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + } + } + m_totalReadLbas++; + m_curLba++; + if (m_curLba >= m_limitLba) { + syncBlocks(); + } + sdError(SD_CARD_ERROR_NONE); + return true; + } + syncBlocks(); + m_readErrors++; + + } + DBG_PRINT() + syncBlocks(); + m_readErrors++; + return false; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readBlocks(uint32_t lba, uint8_t* buf, size_t n) +{ +#if USE_DEBUG_MODE + Serial.print("readBlocks: "); Serial.print(lba); + //Serial.print(", buf: "); Serial.print((uint32_t)buf, HEX); + Serial.print(", "); Serial.println(n); +#endif + volatile bool _state = false; + uint16_t retries = 3; + while ( retries-- ){ + + if ((uint32_t)buf & 3) { + for (size_t i = 0; i < n; i++, lba++, buf += 512) { + if (!readBlock(lba, buf)) { + return false; // readBlock will set errorCode. + } + } + return true; + } + + if (m_curState != READ_STATE || m_curLba != lba) { + #if USE_DEBUG_MODE + Serial.print("New lba, syncing :"); + Serial.println(lba); + #endif + _state = syncBlocks(); + DBG_PRINT(); + if (!_state) { + return false; + } + m_limitLba = (lba + 1024); //arbitrary limit + // prepare DMA for data read transfer + _state = dmaTrxPrepare(buf, 512*n, TRX_RD); + + // prepare SDIO for data read transfer + _state = dmaTrxStart(512*n, TRX_RD); + + // send command to start data transfer + _state = cardCommand(CMD18_XFERTYP, (m_highCapacity ? lba : 512*lba)); + if ( !_state ) { + return sdError(SD_CARD_ERROR_CMD18); + } + m_curLba = lba; + m_curState = READ_STATE; + } + + else { + // prepare DMA for data read transfer + _state = dmaTrxPrepare(buf, 512*n, TRX_RD); + + // prepare SDIO data read transfer + _state = dmaTrxStart(512*n, TRX_RD); + } + + _state = dmaTrxEnd(0); + + if (_state){ + m_totalReadLbas += n; + m_curLba += n; + if (m_curLba >= m_limitLba) { + syncBlocks(); + } + sdError(SD_CARD_ERROR_NONE); + return true; + } + syncBlocks(); + m_readErrors++; + } + DBG_PRINT() + syncBlocks(); + m_readErrors++; + return false; +} +//----------------------------------------------------------------------------- +bool SdioCard::readCID(void* cid) { + memcpy(cid, &m_cid, 16); + return true; +} +//----------------------------------------------------------------------------- +bool SdioCard::readCSD(void* csd) { + memcpy(csd, &m_csd, 16); + return true; +} +/*---------------------------------------------------------------------------*/ +/* replacing this one with DMA support. +bool SdioCard::readData(uint8_t *dst) +{ + //Serial.print("readData: "); Serial.print(m_lba); Serial.print(", m_cnt: "); Serial.println(m_cnt); + if ( m_cnt==0 ) return false; + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // non-DMA block read + trxStart(dst, 512, TRX_RD); + // send command to start data transfer + if ( !cardCommand(CMD17_XFERTYP, (m_highCapacity ? m_lba : 512*m_lba)) ) { + return sdError(SD_CARD_ERROR_CMD17); + } + // Receive a data block from the SDIO + register uint32_t STA; // to speed up SDIO flags checking + register uint16_t cnt = 512; + register uint32_t * ptr = (uint32_t *)dst; + // ----> TIME CRITICAL SECTION BEGIN <---- + do { + STA = SDIO->STA; + if (STA & SDIO_STA_RXFIFOHF) { + // Receive FIFO half full, there are at least 8 words in it + noInterrupts(); + *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; + *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; + interrupts(); + cnt -= 8; + } + } while ( !(STA & (SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) ); + // <---- TIME CRITICAL SECTION END ----> + + // read data still available in FIFO + while ( (SDIO->STA & SDIO_STA_RXDAVL) && (cnt--) ) { + *ptr++ = SDIO->FIFO; + } + // check error, temporary stuff, remove for final version + if ( SDIO->STA & SDIO_STA_TRX_ERROR_FLAGS ) { + _panic("ERROR: non-DMA read error ", SDIO->STA); + return false; + } + m_lba++; + m_cnt--; + return !(SDIO->STA&SDIO_STA_TRX_ERROR_FLAGS); +} +*/ +bool SdioCard::readData(uint8_t *buf) +{ + + volatile bool _state = false; + uint16_t retries = 3; + while ( retries-- ){ + // prepare DMA for data read transfer + _state = dmaTrxPrepare((uint32_t)buf & 3 ? (uint8_t*)aligned : buf, 512, TRX_RD); + + // prepare SDIO data read transfer + _state = dmaTrxStart(512, TRX_RD); + _state = dmaTrxEnd(0); + + if ( _state ) { + if ( (uint32_t)buf & 3 ) { + //memcpy(buf, aligned, 512); + register uint8_t * dst = buf; + register uint8_t * src = (uint8_t *)aligned; + register uint16_t i = 64; + while ( i-- ) { // do 8 byte copies, is much faster than single byte copy + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + } + } + m_curLba += 1; + return true; + } + else { + readStop(); + //_state = dmaTrxPrepare((uint32_t)buf & 3 ? (uint8_t*)aligned : buf, 512, TRX_RD); + //_state = dmaTrxStart(512, TRX_RD); + _state = cardCommand(CMD18_XFERTYP, (m_highCapacity ? m_curLba : 512*m_curLba)); + if ( !_state ) { + return sdError(SD_CARD_ERROR_CMD18); + } + } + } + DBG_PRINT() + m_readErrors++; + return sdError(SD_CARD_ERROR_READ); + +} + + +//----------------------------------------------------------------------------- +bool SdioCard::readOCR(uint32_t* ocr) { + *ocr = m_ocr; + return true; +} +//----------------------------------------------------------------------------- +bool SdioCard::readStart(uint32_t lba) +{ + m_curLba = lba; + /* + m_lba = lba; + m_cnt = 1024; + return true; + */ + volatile bool _state = false; + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + _state = cardCommand(CMD18_XFERTYP, (m_highCapacity ? lba : 512*lba)); + DBG_PRINT(); + if ( !_state ) { + return sdError(SD_CARD_ERROR_CMD18); + } + m_curState = READ_STATE; + return true; +} +/*---------------------------------------------------------------------------*/ +// SDHC will do Auto CMD12 after count blocks. +bool SdioCard::readStart(uint32_t lba, uint32_t count) +{ + //Serial.print("readStart: "); Serial.print(lba); Serial.print(", cnt: "); Serial.println(count); + m_curLba = lba; +/* + m_lba = lba; + m_cnt = count; + return true; +*/ + volatile bool _state = false; + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + _state = cardCommand(CMD18_XFERTYP, (m_highCapacity ? lba : 512*lba)); + DBG_PRINT(); + if ( !_state ) { + return sdError(SD_CARD_ERROR_CMD18); + } + m_curState = READ_STATE; + return true; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readStop() +{ + if ( isEnabledDMA()){ + yieldDmaStatus(); + } + sdio_setup_transfer(0x00FFFFFF, 0, 0); + // Empty SDIO FIFO + while ( SDIO->STA & SDIO_STA_RXDAVL) { + volatile uint32 _unused = SDIO->FIFO; + } + //Serial.println("readStop."); + //m_lba = 0; + if (!trxStop()) { + return false; + } + return true; +} +//----------------------------------------------------------------------------- +inline bool SdioCard::syncBlocks() { +/* if ( isEnabledDMA()){ + waitDmaStatus(); + } +*/ + if (m_curState == READ_STATE) { + m_curState = IDLE_STATE; + if (!readStop()) { + return false; + } + } else if (m_curState == WRITE_STATE) { + m_curState = IDLE_STATE; + return writeStop(); + } + return true; +} +//----------------------------------------------------------------------------- +uint8_t SdioCard::type() { + return m_version2 ? m_highCapacity ? + SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeBlock(uint32_t lba, const uint8_t* buf) +{ +#if USE_DEBUG_MODE + Serial.print("writeBlock: "); Serial.println(lba); //Serial.print(", buf: "); Serial.println((uint32_t)buf, HEX); +#endif + uint8_t * ptr = (uint8_t *)buf; + if (3 & (uint32_t)ptr) { + Serial.print("writeBlock: "); Serial.print(lba); + Serial.print(", buf: "); Serial.print((uint32_t)ptr, HEX); + //memcpy(aligned, buf, 512); + register uint8_t * src = (uint8_t *)ptr; + ptr = (uint8_t *)aligned; + register uint8_t * dst = ptr; + register uint16_t i = 64; + while ( i-- ) { // do 8 byte copies, is much faster than single byte copy + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + } + } + + + + if (m_curState != WRITE_STATE || m_curLba != lba) { + if (!syncBlocks()) { + return false; + } + + m_limitLba = (lba + 1024); //arbitrary limit + + // prepare DMA for data transfer + dmaTrxPrepare(ptr, 512, TRX_WR); // 1 block, write transfer + + // send command to start data transfer + if ( !cardCommand(CMD25_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD25); + } + m_curLba = lba; + m_curState = WRITE_STATE; + + } + else { + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // prepare DMA for data transfer + dmaTrxPrepare(ptr, 512, TRX_WR); // 1 block, write transfer + } + + // prepare SDIO for data transfer + dmaTrxStart(512, TRX_WR); // 1 block, write transfer + + if (!dmaTrxEnd(0)){ + m_curState = IDLE_STATE; + m_writeErrors++; + return false; + } + m_curLba++; + if (m_curLba >= m_limitLba) { + syncBlocks(); + } + return true; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeBlocks(uint32_t lba, const uint8_t* buf, size_t n) +{ +#if USE_DEBUG_MODE + Serial.print("writeBlocks: "); Serial.print(lba); + //Serial.print(", buf: "); Serial.print((uint32_t)buf, HEX); + Serial.print(", "); Serial.println(n); +#endif + if (3 & (uint32_t)buf) { // misaligned buffer address, write single blocks + for (size_t i = 0; i < n; i++, lba++, buf += 512) { + if (!writeBlock(lba, buf)) { + return false; // writeBlock will set errorCode. + } + } + return true; + } + if (yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } +#if 0 + // set number of blocks to write - this can speed up block write + if ( !cardAcmd(m_rca, ACMD23_XFERTYP, n) ) { + return sdError(SD_CARD_ERROR_ACMD23); + } +#endif + + if (m_curState != WRITE_STATE || m_curLba != lba) { + if (!syncBlocks()) { + return false; + } + + m_limitLba = (lba + 1024); //arbitrary limit, 512KB + // prepare DMA for data transfer + dmaTrxPrepare((uint8_t *)buf, 512*n, TRX_WR); // n blocks, write transfer + + // send command to start data transfer + if ( !cardCommand(CMD25_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD25); + } + m_curLba = lba; + m_curState = WRITE_STATE; + + } + else { + // prepare DMA for data transfer + dmaTrxPrepare((uint8_t *)buf, 512*n, TRX_WR); // n blocks, write transfer + } + + // prepare SDIO for data transfer + dmaTrxStart(512*n, TRX_WR); // n blocks, write transfer + + if (!dmaTrxEnd(0)){ + m_writeErrors++; + m_curState = IDLE_STATE; + return false; + } + m_curLba += n; + if (m_curLba >= m_limitLba) { + syncBlocks(); + } + return true; + +} +/*---------------------------------------------------------------------------*/ +/* +bool SdioCard::writeData(const uint8_t* src) +{ + //Serial.print("writeData: "); Serial.print(m_lba); Serial.print(", cnt: "); Serial.println(m_cnt); + if ( !m_cnt ) return false; + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // send command to start block data transfer + if ( !cardCommand(CMD24_XFERTYP, (m_highCapacity ? m_lba : 512*m_lba)) ) { + return sdError(SD_CARD_ERROR_CMD24); + } + // non-DMA block write + trxStart((uint8_t*)src, 512, TRX_WR); + // Receive a data block from the SDIO + register uint32_t STA; // to speed up SDIO flags checking + register uint16_t cnt = 512; + register uint32_t * ptr = (uint32_t*)src; + // pre-fill up the FIFO with 32 words + noInterrupts(); + while ( (cnt--)>(512-32) ) SDIO->FIFO = *ptr++; + interrupts(); + // ----> TIME CRITICAL SECTION BEGIN <---- + do { + STA = SDIO->STA; + if (STA & SDIO_STA_TXFIFOHE) { + // Transmit FIFO half empty, fill up the remaining 16 words + noInterrupts(); + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + interrupts(); + cnt -= 16; + } + } while ( !(STA & (SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) && cnt); + // <---- TIME CRITICAL SECTION END ----> + if ( waitTimeout(isBusyTransferComplete) ) { + return sdError(SD_CARD_ERROR_WRITE_TIMEOUT); + } + m_lba++; + m_cnt--; + if (SDIO->STA&SDIO_STA_TRX_ERROR_FLAGS) { + _panic("writeData error: ", SDIO->STA); + } + return !(SDIO->STA&SDIO_STA_TRX_ERROR_FLAGS); +} +*/ +bool SdioCard::writeData(const uint8_t* src) +{ + uint8_t * ptr = (uint8_t *)src; + if (3 & (uint32_t)ptr) { + Serial.print("writeBlock: "); Serial.print(m_curLba); + Serial.print(", buf: "); Serial.print((uint32_t)ptr, HEX); + //memcpy(aligned, buf, 512); + register uint8_t * src = (uint8_t *)ptr; + ptr = (uint8_t *)aligned; + register uint8_t * dst = ptr; + register uint16_t i = 64; + while ( i-- ) { // do 8 byte copies, is much faster than single byte copy + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + } + } + + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // prepare DMA for data transfer + dmaTrxPrepare(ptr, 512, TRX_WR); // 1 block, write transfer + DBG_PRINT(); + + // prepare SDIO for data transfer + dmaTrxStart(512, TRX_WR); // 1 block, write transfer + DBG_PRINT(); + + if (!dmaTrxEnd(0)){ + m_writeErrors++; + return false; + } + return true; +} +//----------------------------------------------------------------------------- +bool SdioCard::writeStart(uint32_t lba) +{ + /* + m_lba = lba; + m_cnt = 1024; + return true; + */ + DBG_PRINT(); + m_curLba = lba; + if (yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + if ( !cardCommand(CMD25_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD25); + } + m_curState = WRITE_STATE; + return true; +} +/*---------------------------------------------------------------------------*/ +// SDHC will do Auto CMD12 after count blocks. +bool SdioCard::writeStart(uint32_t lba, uint32_t count) +{ + //Serial.print("writeStart: "); Serial.print(lba); Serial.print(", cnt: "); Serial.println(count); + /* + m_lba = lba; + m_cnt = count; + return true; + */ + m_curLba = lba; + if (yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + if ( !cardCommand(CMD25_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD25); + } + m_curState = WRITE_STATE; + return true; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeStop() +{ + if ( isEnabledDMA()){ + if ( !yieldDmaStatus() ) { + DBG_PRINT(); + return sdError(SD_CARD_ERROR_DMA); + } + } + //m_lba = 0; + m_curState = IDLE_STATE; + return trxStop(); + //Serial.println("writeStop."); +} diff --git a/STM32F1/libraries/SDIO/SdioF1.h b/STM32F1/libraries/SDIO/SdioF1.h new file mode 100644 index 0000000..efa4774 --- /dev/null +++ b/STM32F1/libraries/SDIO/SdioF1.h @@ -0,0 +1,7 @@ + +#ifndef _SDIOF1_H_ +#define _SDIOF1_H_ + +#include + +#endif diff --git a/STM32F1/libraries/SPI/examples/spi_slave/spi_slave.ino b/STM32F1/libraries/SPI/examples/spi_slave/spi_slave.ino new file mode 100644 index 0000000..1e26db3 --- /dev/null +++ b/STM32F1/libraries/SPI/examples/spi_slave/spi_slave.ino @@ -0,0 +1,37 @@ +// SPI full-duplex slave example +// STM32 acts as a SPI slave and reads 8 bit data frames over SPI. +// Master also gets a reply from the slave, which is a a simple count (0, 1, 2, 3) +// that is incremented each time a data frame is received. +// Serial output is here for debug + +#include +#include + +void setupSPI(void) +{ + // The clock value is not used + // SPI1 is selected by default + // MOSI, MISO, SCK and NSS PINs are set by the library + SPI.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); +} + +void setup() +{ + Serial.begin(115200); + delay(100); + setupSPI(); +} + +uint8_t count = 0; +void loop() +{ + // Blocking call to read SPI message + uint8_t msg = SPI.transfer(++count); + Serial.print("Received = 0b"); + Serial.print(msg, BIN); + Serial.print(", 0x"); + Serial.print(msg, HEX); + Serial.print(", "); + Serial.println(msg); +} + diff --git a/STM32F1/libraries/SPI/src/SPI.cpp b/STM32F1/libraries/SPI/src/SPI.cpp index 4eeec38..4d8787d 100644 --- a/STM32F1/libraries/SPI/src/SPI.cpp +++ b/STM32F1/libraries/SPI/src/SPI.cpp @@ -31,7 +31,6 @@ #include "SPI.h" -//#define SPI_DEBUG #include #include @@ -41,6 +40,8 @@ #include "boards.h" //#include "HardwareSerial.h" +/** Time in ms for DMA receive timeout */ +#define DMA_TIMEOUT 100 #if CYCLES_PER_MICROSECOND != 72 /* TODO [0.2.0?] something smarter than this */ @@ -90,79 +91,80 @@ static const spi_pins board_spi_pins[] __FLASH__ = { * Constructor */ -SPIClass::SPIClass(uint32 spi_num) { +SPIClass::SPIClass(uint32 spi_num) +{ + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed - _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed - - switch (spi_num) { #if BOARD_NR_SPI >= 1 case 1: _currentSetting->spi_d = SPI1; + _spi1_this = (void*) this; break; #endif #if BOARD_NR_SPI >= 2 case 2: _currentSetting->spi_d = SPI2; + _spi2_this = (void*) this; break; #endif #if BOARD_NR_SPI >= 3 case 3: _currentSetting->spi_d = SPI3; + _spi3_this = (void*) this; break; #endif default: ASSERT(0); } - - // Init things specific to each SPI device - // clock divider setup is a bit of hack, and needs to be improved at a later date. - _settings[0].spi_d = SPI1; - _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); - _settings[0].spiDmaDev = DMA1; - _settings[0].spiTxDmaChannel = DMA_CH3; - _settings[0].spiRxDmaChannel = DMA_CH2; - _settings[1].spi_d = SPI2; - _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); - _settings[1].spiDmaDev = DMA1; - _settings[1].spiTxDmaChannel = DMA_CH5; - _settings[1].spiRxDmaChannel = DMA_CH4; + + // Init things specific to each SPI device + // clock divider setup is a bit of hack, and needs to be improved at a later date. + _settings[0].spi_d = SPI1; + _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); + _settings[0].spiDmaDev = DMA1; + _settings[0].spiTxDmaChannel = DMA_CH3; + _settings[0].spiRxDmaChannel = DMA_CH2; + _settings[1].spi_d = SPI2; + _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); + _settings[1].spiDmaDev = DMA1; + _settings[1].spiTxDmaChannel = DMA_CH5; + _settings[1].spiRxDmaChannel = DMA_CH4; #if BOARD_NR_SPI >= 3 - _settings[2].spi_d = SPI3; - _settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock); - _settings[2].spiDmaDev = DMA2; - _settings[2].spiTxDmaChannel = DMA_CH2; - _settings[2].spiRxDmaChannel = DMA_CH1; -#endif - - //pinMode(BOARD_SPI_DEFAULT_SS,OUTPUT); + _settings[2].spi_d = SPI3; + _settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock); + _settings[2].spiDmaDev = DMA2; + _settings[2].spiTxDmaChannel = DMA_CH2; + _settings[2].spiRxDmaChannel = DMA_CH1; +#endif + + // added for DMA callbacks. + _currentSetting->state = SPI_STATE_IDLE; } /* * Set up/tear down */ void SPIClass::updateSettings(void) { - uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE | SPI_SOFT_SS); - #ifdef SPI_DEBUG - Serial.print("spi_master_enable("); Serial.print(_currentSetting->clockDivider); Serial.print(","); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")"); - #endif - spi_master_enable(_currentSetting->spi_d, (spi_baud_rate)_currentSetting->clockDivider, (spi_mode)_currentSetting->dataMode, flags); + uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE | SPI_SOFT_SS); + spi_master_enable(_currentSetting->spi_d, (spi_baud_rate)_currentSetting->clockDivider, (spi_mode)_currentSetting->dataMode, flags); } void SPIClass::begin(void) { spi_init(_currentSetting->spi_d); configure_gpios(_currentSetting->spi_d, 1); updateSettings(); + // added for DMA callbacks. + _currentSetting->state = SPI_STATE_READY; } void SPIClass::beginSlave(void) { spi_init(_currentSetting->spi_d); configure_gpios(_currentSetting->spi_d, 0); - uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE); - #ifdef SPI_DEBUG - Serial.print("spi_slave_enable("); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")"); - #endif + uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize); spi_slave_enable(_currentSetting->spi_d, (spi_mode)_currentSetting->dataMode, flags); + // added for DMA callbacks. + _currentSetting->state = SPI_STATE_READY; } void SPIClass::end(void) { @@ -181,28 +183,25 @@ void SPIClass::end(void) { while (spi_is_busy(_currentSetting->spi_d)) ; spi_peripheral_disable(_currentSetting->spi_d); + // added for DMA callbacks. + // Need to add unsetting the callbacks for the DMA channels. + _currentSetting->state = SPI_STATE_IDLE; } /* Roger Clark added 3 functions */ void SPIClass::setClockDivider(uint32_t clockDivider) { - #ifdef SPI_DEBUG - Serial.print("Clock divider set to "); Serial.println(clockDivider); - #endif - _currentSetting->clockDivider = clockDivider; - uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_BR); - _currentSetting->spi_d->regs->CR1 = cr1 | (clockDivider & SPI_CR1_BR); + _currentSetting->clockDivider = clockDivider; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_BR); + _currentSetting->spi_d->regs->CR1 = cr1 | (clockDivider & SPI_CR1_BR); } void SPIClass::setBitOrder(BitOrder bitOrder) { - #ifdef SPI_DEBUG - Serial.print("Bit order set to "); Serial.println(bitOrder); - #endif - _currentSetting->bitOrder = bitOrder; - uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_LSBFIRST); - if ( bitOrder==LSBFIRST ) cr1 |= SPI_CR1_LSBFIRST; - _currentSetting->spi_d->regs->CR1 = cr1; + _currentSetting->bitOrder = bitOrder; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_LSBFIRST); + if ( bitOrder==LSBFIRST ) cr1 |= SPI_CR1_LSBFIRST; + _currentSetting->spi_d->regs->CR1 = cr1; } /* Victor Perez. Added to test changing datasize from 8 to 16 bit modes on the fly. @@ -211,9 +210,11 @@ void SPIClass::setBitOrder(BitOrder bitOrder) */ void SPIClass::setDataSize(uint32 datasize) { - _currentSetting->dataSize = datasize; - uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF); - _currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF); + _currentSetting->dataSize = datasize; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF); + uint8 en = spi_is_enabled(_currentSetting->spi_d); + spi_peripheral_disable(_currentSetting->spi_d); + _currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF) | en; } void SPIClass::setDataMode(uint8_t dataMode) @@ -243,59 +244,44 @@ bit 0 - CPHA : Clock phase If someone finds this is not the case or sees a logic error with this let me know ;-) */ - #ifdef SPI_DEBUG - Serial.print("Data mode set to "); Serial.println(dataMode); - #endif - _currentSetting->dataMode = dataMode; - uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_CPOL|SPI_CR1_CPHA); - _currentSetting->spi_d->regs->CR1 = cr1 | (dataMode & (SPI_CR1_CPOL|SPI_CR1_CPHA)); + _currentSetting->dataMode = dataMode; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_CPOL|SPI_CR1_CPHA); + _currentSetting->spi_d->regs->CR1 = cr1 | (dataMode & (SPI_CR1_CPOL|SPI_CR1_CPHA)); } void SPIClass::beginTransaction(uint8_t pin, SPISettings settings) { - #ifdef SPI_DEBUG - Serial.println("SPIClass::beginTransaction"); - #endif - //_SSPin=pin; - //pinMode(_SSPin,OUTPUT); - //digitalWrite(_SSPin,LOW); - setBitOrder(settings.bitOrder); - setDataMode(settings.dataMode); - setDataSize(settings.dataSize); - setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock)); - begin(); + setBitOrder(settings.bitOrder); + setDataMode(settings.dataMode); + setDataSize(settings.dataSize); + setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock)); + begin(); } void SPIClass::beginTransactionSlave(SPISettings settings) { - #ifdef SPI_DEBUG - Serial.println(F("SPIClass::beginTransactionSlave")); - #endif - setBitOrder(settings.bitOrder); - setDataMode(settings.dataMode); - setDataSize(settings.dataSize); - beginSlave(); + setBitOrder(settings.bitOrder); + setDataMode(settings.dataMode); + setDataSize(settings.dataSize); + beginSlave(); } void SPIClass::endTransaction(void) { - #ifdef SPI_DEBUG - Serial.println("SPIClass::endTransaction"); - #endif - //digitalWrite(_SSPin,HIGH); + //digitalWrite(_SSPin,HIGH); #if false // code from SAM core - uint8_t mode = interruptMode; - if (mode > 0) { - if (mode < 16) { - if (mode & 1) PIOA->PIO_IER = interruptMask[0]; - if (mode & 2) PIOB->PIO_IER = interruptMask[1]; - if (mode & 4) PIOC->PIO_IER = interruptMask[2]; - if (mode & 8) PIOD->PIO_IER = interruptMask[3]; - } else { - if (interruptSave) interrupts(); - } - } + uint8_t mode = interruptMode; + if (mode > 0) { + if (mode < 16) { + if (mode & 1) PIOA->PIO_IER = interruptMask[0]; + if (mode & 2) PIOB->PIO_IER = interruptMask[1]; + if (mode & 4) PIOC->PIO_IER = interruptMask[2]; + if (mode & 8) PIOD->PIO_IER = interruptMask[3]; + } else { + if (interruptSave) interrupts(); + } + } #endif } @@ -304,211 +290,354 @@ void SPIClass::endTransaction(void) * I/O */ -uint8 SPIClass::read(void) { - uint8 buf[1]; - this->read(buf, 1); - return buf[0]; +uint16 SPIClass::read(void) +{ + while ( spi_is_rx_nonempty(_currentSetting->spi_d)==0 ) ; + return (uint16)spi_rx_reg(_currentSetting->spi_d); } -void SPIClass::read(uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (rxed < len) { - while (!spi_is_rx_nonempty(_currentSetting->spi_d)) - ; - buf[rxed++] = (uint8)spi_rx_reg(_currentSetting->spi_d); +void SPIClass::read(uint8 *buf, uint32 len) +{ + if ( len == 0 ) return; + spi_rx_reg(_currentSetting->spi_d); // clear the RX buffer in case a byte is waiting on it. + spi_reg_map * regs = _currentSetting->spi_d->regs; + // start sequence: write byte 0 + regs->DR = 0x00FF; // write the first byte + // main loop + while ( (--len) ) { + while( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag + noInterrupts(); // go atomic level - avoid interrupts to surely get the previously received data + regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag. + while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register + *buf++ = (uint8)(regs->DR); // read and store the received byte. This clears the RXNE flag. + interrupts(); // let systick do its job } + // read remaining last byte + while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the Rx register + *buf++ = (uint8)(regs->DR); // read and store the received byte } -void SPIClass::write(uint16 data) { - // this->write(&data, 1); - - /* Added for 16bit data Victor Perez. Roger Clark - * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte) - * The original method, of calling write(*data, length) . - * This almost doubles the speed of this function. - */ - - spi_tx_reg(_currentSetting->spi_d, data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." - while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." +void SPIClass::write(uint16 data) +{ + /* Added for 16bit data Victor Perez. Roger Clark + * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, + * by taking the Tx code from transfer(byte) + * This almost doubles the speed of this function. + */ + spi_tx_reg(_currentSetting->spi_d, data); // write the data to be transmitted into the SPI_DR register (this clears the TXE flag) + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." } -//void SPIClass::write(uint8 byte) { - // this->write(&byte, 1); +void SPIClass::write16(uint16 data) +{ + // Added by stevestrong: write two consecutive bytes in 8 bit mode (DFF=0) + spi_tx_reg(_currentSetting->spi_d, data>>8); // write high byte + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // Wait until TXE=1 + spi_tx_reg(_currentSetting->spi_d, data); // write low byte + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // Wait until TXE=1 + while (spi_is_busy(_currentSetting->spi_d) != 0); // wait until BSY=0 +} - /* Roger Clark - * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte) - * The original method, of calling write(*data, length) . - * This almost doubles the speed of this function. - */ - -// spi_tx_reg(_currentSetting->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." -// while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." -// while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." -//} - -void SPIClass::write(const uint8 *data, uint32 length) { - uint32 txed = 0; - while (txed < length) { - txed += spi_tx(_currentSetting->spi_d, data + txed, length - txed); +void SPIClass::write(uint16 data, uint32 n) +{ + // Added by stevstrong: Repeatedly send same data by the specified number of times + spi_reg_map * regs = _currentSetting->spi_d->regs; + while ( (n--)>0 ) { + regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag) + while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty } - while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "4. After writing the last data item into the SPI_DR register, wait until TXE=1 ..." - while (spi_is_busy(_currentSetting->spi_d) != 0); // "... then wait until BSY=0, this indicates that the transmission of the last data is complete." - // taken from SdSpiSTM32F1.cpp - Victor's lib, and adapted to support device selection - if (spi_is_rx_nonempty(_currentSetting->spi_d)) { - uint8_t b = spi_rx_reg(_currentSetting->spi_d); - } + while ( (regs->SR & SPI_SR_BSY) != 0); // wait until BSY=0 before returning } -uint16_t SPIClass::transfer16(uint16_t wr_data) const { - spi_tx_reg(_currentSetting->spi_d, wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." - while (spi_is_rx_nonempty(_currentSetting->spi_d) == 0); // "4. Wait until RXNE=1 ..." - uint16_t rd_data = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." -// while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." -// while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - return rd_data; +void SPIClass::write(const void *data, uint32 length) +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_tx(spi_d, data, length); // data can be array of bytes or words + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." } -uint8 SPIClass::transfer(uint8 byte) const { - spi_tx_reg(_currentSetting->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." - while (spi_is_rx_nonempty(_currentSetting->spi_d) == 0); // "4. Wait until RXNE=1 ..." - uint8 b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." - while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - return b; +uint8 SPIClass::transfer(uint8 byte) const +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_rx_reg(spi_d); // read any previous data + spi_tx_reg(spi_d, byte); // Write the data item to be transmitted into the SPI_DR register + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + return (uint8)spi_rx_reg(spi_d); // "... and read the last received data." } + +uint16_t SPIClass::transfer16(uint16_t data) const +{ + // Modified by stevestrong: write & read two consecutive bytes in 8 bit mode (DFF=0) + // This is more effective than two distinct byte transfers + spi_dev * spi_d = _currentSetting->spi_d; + spi_rx_reg(spi_d); // read any previous data + spi_tx_reg(spi_d, data>>8); // write high byte + while (spi_is_tx_empty(spi_d) == 0); // wait until TXE=1 + while (spi_is_busy(spi_d) != 0); // wait until BSY=0 + uint16_t ret = spi_rx_reg(spi_d)<<8; // read and shift high byte + spi_tx_reg(spi_d, data); // write low byte + while (spi_is_tx_empty(spi_d) == 0); // wait until TXE=1 + while (spi_is_busy(spi_d) != 0); // wait until BSY=0 + ret += spi_rx_reg(spi_d); // read low byte + return ret; +} + /* Roger Clark and Victor Perez, 2015 * Performs a DMA SPI transfer with at least a receive buffer. * If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer. * On exit TX buffer is not modified, and RX buffer cotains the received data. * Still in progress. */ -uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length) { - if (length == 0) return 0; - uint8 b = 0; - if (spi_is_rx_nonempty(_currentSetting->spi_d) == 1) b = spi_rx_reg(_currentSetting->spi_d); //Clear the RX buffer in case a byte is waiting on it. -// dma1_ch3_Active=true; +void SPIClass::dmaTransferSet(const void *transmitBuf, void *receiveBuf) { dma_init(_currentSetting->spiDmaDev); -// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); - - // RX - spi_rx_dma_enable(_currentSetting->spi_d); - dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, - receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA - dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length); - - // TX - spi_tx_dma_enable(_currentSetting->spi_d); - if (!transmitBuf) { - static uint8_t ff = 0XFF; - transmitBuf = &ff; - dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, - transmitBuf, DMA_SIZE_8BITS, (DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit FF repeatedly - } - else { - dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, - transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit buffer DMA - } - dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); - - dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive - dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit - -// while (dma1_ch3_Active); -// if (receiveBuf) { - uint32_t m = millis(); - while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0) {//Avoid interrupts and just loop waiting for the flag to be set. - if ((millis() - m) > 100) { -// dma1_ch3_Active = 0; - b = 2; - break; - } + //spi_rx_dma_enable(_currentSetting->spi_d); + //spi_tx_dma_enable(_currentSetting->spi_d); + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + receiveBuf, dma_bit_size, (DMA_MINC_MODE | DMA_TRNS_CMPLT ));// receive buffer DMA + if (!transmitBuf) { + transmitBuf = &ff; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, (DMA_FROM_MEM));// Transmit FF repeatedly } - dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + else { + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, (DMA_MINC_MODE | DMA_FROM_MEM ));// Transmit buffer DMA + } + dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, DMA_PRIORITY_LOW); + dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, DMA_PRIORITY_VERY_HIGH); +} -// } - while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." +uint8 SPIClass::dmaTransferRepeat(uint16 length) { + if (length == 0) return 0; + if (spi_is_rx_nonempty(_currentSetting->spi_d) == 1) spi_rx_reg(_currentSetting->spi_d); + _currentSetting->state = SPI_STATE_TRANSFER; + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit + spi_rx_dma_enable(_currentSetting->spi_d); + spi_tx_dma_enable(_currentSetting->spi_d); + if (_currentSetting->receiveCallback){ + return 0; + } + //uint32_t m = millis(); + uint8 b = 0; + uint32_t m = millis(); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) { + //Avoid interrupts and just loop waiting for the flag to be set. + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } + + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + spi_rx_dma_disable(_currentSetting->spi_d); dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); - dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); - spi_rx_dma_disable(_currentSetting->spi_d); // And disable generation of DMA request from the SPI port so other peripherals can use the channels - spi_tx_dma_disable(_currentSetting->spi_d); - if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..." - uint8 x = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." - } + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_READY; return b; } +/* Roger Clark and Victor Perez, 2015 +* Performs a DMA SPI transfer with at least a receive buffer. +* If a TX buffer is not provided, FF is sent over and over for the length of the transfer. +* On exit TX buffer is not modified, and RX buffer contains the received data. +* Still in progress. +*/ + +uint8 SPIClass::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16 length) { + dmaTransferSet(transmitBuf, receiveBuf); + return dmaTransferRepeat(length); +} + /* Roger Clark and Victor Perez, 2015 * Performs a DMA SPI send using a TX buffer. * On exit TX buffer is not modified. * Still in progress. +* 2016 - stevstrong - reworked to automatically detect bit size from SPI setting */ -uint8 SPIClass::dmaSend(uint8 *transmitBuf, uint16 length, bool minc) { - if (length == 0) return 0; - uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); - uint8 b = 0; -// dma1_ch3_Active=true; - dma_init(_currentSetting->spiDmaDev); -// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); - // TX - spi_tx_dma_enable(_currentSetting->spi_d); - dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, - transmitBuf, DMA_SIZE_8BITS, flags);// Transmit buffer DMA - dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); - dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit - -// while (dma1_ch3_Active); - while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0); //Avoid interrupts and just loop waiting for the flag to be set. - dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); +void SPIClass::dmaSendSet(const void * transmitBuf, bool minc) { + uint32 flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); + dma_init(_currentSetting->spiDmaDev); + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, flags);// Transmit buffer DMA + dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, DMA_PRIORITY_LOW); +} - while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); - spi_tx_dma_disable(_currentSetting->spi_d); - if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..." - uint8 x = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." - } +uint8 SPIClass::dmaSendRepeat(uint16 length) { + if (length == 0) return 0; + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + _currentSetting->state = SPI_STATE_TRANSMIT; + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit + spi_tx_dma_enable(_currentSetting->spi_d); + if (_currentSetting->transmitCallback) + { + return 0; + } + uint32_t m = millis(); + uint8 b = 0; + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) { + //Avoid interrupts and just loop waiting for the flag to be set. + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_READY; return b; } -uint8 SPIClass::dmaSend(uint16 *transmitBuf, uint16 length, bool minc) { - if (length == 0) return 0; - uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); - uint8 b; - dma1_ch3_Active=true; +uint8 SPIClass::dmaSend(const void * transmitBuf, uint16 length, bool minc) { + dmaSendSet(transmitBuf, minc); + return dmaSendRepeat(length); +} + +uint8 SPIClass::dmaSendAsync(const void * transmitBuf, uint16 length, bool minc) { + uint8 b = 0; + + if (_currentSetting->state != SPI_STATE_READY) + { + + uint32_t m = millis(); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) {//Avoid interrupts and just loop waiting for the flag to be set. + //delayMicroseconds(10); + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } + + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_READY; + } + + if (length == 0) return 0; + uint32 flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); + dma_init(_currentSetting->spiDmaDev); -// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); + // TX + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, flags);// Transmit buffer DMA + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit + spi_tx_dma_enable(_currentSetting->spi_d); - // TX - spi_tx_dma_enable(_currentSetting->spi_d); - dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_16BITS, - transmitBuf, DMA_SIZE_16BITS, flags);// Transmit buffer DMA - dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); - dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit - -// while (dma1_ch3_Active); - while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0); //Avoid interrupts and just loop waiting for the flag to be set. - dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_TRANSMIT; - while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); - spi_tx_dma_disable(_currentSetting->spi_d); - if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..." - b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." - } return b; } +/* + New functions added to manage callbacks. + Victor Perez 2017 +*/ + +void SPIClass::onReceive(void(*callback)(void)) { + _currentSetting->receiveCallback = callback; + if (callback){ + switch (_currentSetting->spi_d->clk_id) { + case RCC_SPI1: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi1EventCallback); + break; + case RCC_SPI2: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi2EventCallback); + break; + #if BOARD_NR_SPI >= 3 + case RCC_SPI3: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi3EventCallback); + break; + #endif + default: + ASSERT(0); + } + } + else { + dma_detach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + } +} + +void SPIClass::onTransmit(void(*callback)(void)) { + _currentSetting->transmitCallback = callback; + if (callback){ + switch (_currentSetting->spi_d->clk_id) { + case RCC_SPI1: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi1EventCallback); + break; + case RCC_SPI2: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi2EventCallback); + break; + #if BOARD_NR_SPI >= 3 + case RCC_SPI3: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi3EventCallback); + break; + #endif + default: + ASSERT(0); + } + } + else { + dma_detach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + } +} + +/* + TODO: check if better to first call the customer code, next disable the DMA requests. + Also see if we need to check whether callbacks are set or not, may be better to be checked during the initial setup and only set the callback to EventCallback if they are set. +*/ + +void SPIClass::EventCallback() { + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0" + switch (_currentSetting->state) { + case SPI_STATE_TRANSFER: + while (spi_is_rx_nonempty(_currentSetting->spi_d)); + _currentSetting->state = SPI_STATE_READY; + spi_tx_dma_disable(_currentSetting->spi_d); + spi_rx_dma_disable(_currentSetting->spi_d); + //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + + if (_currentSetting->receiveCallback) + { + _currentSetting->receiveCallback(); + } + break; + case SPI_STATE_TRANSMIT: + _currentSetting->state = SPI_STATE_READY; + spi_tx_dma_disable(_currentSetting->spi_d); + //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + if (_currentSetting->transmitCallback) + { + _currentSetting->transmitCallback(); + } + + break; + default: + // we shouldn't get here, so better to add an assert and fail. + return; + } +} + void SPIClass::attachInterrupt(void) { - // Should be enableInterrupt() + // Should be enableInterrupt() } void SPIClass::detachInterrupt(void) { - // Should be disableInterrupt() + // Should be disableInterrupt() } /* @@ -536,28 +665,39 @@ uint8 SPIClass::nssPin(void) { */ uint8 SPIClass::send(uint8 data) { - uint8 buf[] = {data}; - return this->send(buf, 1); + this->write(data); + return 1; } uint8 SPIClass::send(uint8 *buf, uint32 len) { - uint32 txed = 0; - uint8 ret = 0; - while (txed < len) { - this->write(buf[txed++]); - ret = this->read(); - } - return ret; + this->write(buf, len); + return len; } uint8 SPIClass::recv(void) { return this->read(); } - /* - * Auxiliary functions - */ + DMA call back functions, one per port. +*/ + +void SPIClass::_spi1EventCallback() +{ + reinterpret_cast(_spi1_this)->EventCallback(); +} + +void SPIClass::_spi2EventCallback() { + reinterpret_cast(_spi2_this)->EventCallback(); +} +#if BOARD_NR_SPI >= 3 +void SPIClass::_spi3EventCallback() { + reinterpret_cast(_spi3_this)->EventCallback(); +} +#endif +/* +* Auxiliary functions +*/ static const spi_pins* dev_to_spi_pins(spi_dev *dev) { switch (dev->clk_id) { @@ -598,8 +738,8 @@ static void configure_gpios(spi_dev *dev, bool as_master) { disable_pwm(mosii); spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit, - scki->gpio_device, scki->gpio_bit, misoi->gpio_bit, - mosii->gpio_bit); + scki->gpio_device, scki->gpio_bit, misoi->gpio_bit, + mosii->gpio_bit); } static const spi_baud_rate baud_rates[8] __FLASH__ = { @@ -614,26 +754,23 @@ static const spi_baud_rate baud_rates[8] __FLASH__ = { }; /* - * Note: This assumes you're on a LeafLabs-style board - * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). - */ +* Note: This assumes you're on a LeafLabs-style board +* (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). +*/ static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) { - uint32_t clock = 0, i; - #ifdef SPI_DEBUG - Serial.print("determine_baud_rate("); Serial.print(freq); Serial.println(")"); - #endif + uint32_t clock = 0, i; switch (rcc_dev_clk(dev->clk_id)) { - case RCC_APB2: clock = STM32_PCLK2; break; // 72 Mhz - case RCC_APB1: clock = STM32_PCLK1; break; // 36 Mhz + case RCC_APB2: clock = STM32_PCLK2; break; // 72 Mhz + case RCC_APB1: clock = STM32_PCLK1; break; // 36 Mhz } clock /= 2; i = 0; while (i < 7 && freq < clock) { - clock /= 2; - i++; + clock /= 2; + i++; } - return baud_rates[i]; + return baud_rates[i]; } SPIClass SPI(1); diff --git a/STM32F1/libraries/SPI/src/SPI.h b/STM32F1/libraries/SPI/src/SPI.h index e949051..686d23d 100644 --- a/STM32F1/libraries/SPI/src/SPI.h +++ b/STM32F1/libraries/SPI/src/SPI.h @@ -99,6 +99,13 @@ #define DATA_SIZE_8BIT SPI_CR1_DFF_8_BIT #define DATA_SIZE_16BIT SPI_CR1_DFF_16_BIT +typedef enum { + SPI_STATE_IDLE, + SPI_STATE_READY, + SPI_STATE_RECEIVE, + SPI_STATE_TRANSMIT, + SPI_STATE_TRANSFER + } spi_mode_t; class SPISettings { public: SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { @@ -115,6 +122,13 @@ public: init_MightInline(clock, bitOrder, dataMode, dataSize); } } + SPISettings(uint32_t clock) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); + } else { + init_MightInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); + } + } SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); } private: void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { @@ -127,21 +141,31 @@ private: this->dataSize = dataSize; } uint32_t clock; + uint32_t dataSize; + uint32_t clockDivider; BitOrder bitOrder; uint8_t dataMode; - uint32_t dataSize; - + uint8_t _SSPin; + volatile spi_mode_t state; spi_dev *spi_d; - uint8_t _SSPin; - uint32_t clockDivider; dma_channel spiRxDmaChannel, spiTxDmaChannel; dma_dev* spiDmaDev; + void (*receiveCallback)(void) = NULL; + void (*transmitCallback)(void) = NULL; friend class SPIClass; }; -volatile static bool dma1_ch3_Active; +/* + Should move this to within the class once tested out, just for tidyness +*/ +static uint8_t ff = 0XFF; +static void (*_spi1_this); +static void (*_spi2_this); +#if BOARD_NR_SPI >= 3 +static void (*_spi3_this); +#endif /** * @brief Wirish SPI interface. @@ -152,8 +176,6 @@ volatile static bool dma1_ch3_Active; class SPIClass { public: - - /** * @param spiPortNumber Number of the SPI port to manage. */ @@ -163,8 +185,6 @@ public: * Set up/tear down */ - - /** * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). */ @@ -210,46 +230,55 @@ public: */ void setDataSize(uint32 ds); - + /* Victor Perez 2017. Added to set and clear callback functions for callback + * on DMA transfer completion. + * onReceive used to set the callback in case of dmaTransfer (tx/rx), once rx is completed + * onTransmit used to set the callback in case of dmaSend (tx only). That function + * will NOT be called in case of TX/RX + */ + void onReceive(void(*)(void)); + void onTransmit(void(*)(void)); + /* * I/O */ /** - * @brief Return the next unread byte. + * @brief Return the next unread byte/word. * - * If there is no unread byte waiting, this function will block + * If there is no unread byte/word waiting, this function will block * until one is received. */ - uint8 read(void); + uint16 read(void); /** * @brief Read length bytes, storing them into buffer. * @param buffer Buffer to store received bytes into. - * @param length Number of bytes to store in buffer. This + * @param length Number of bytes to store in buffer. This * function will block until the desired number of * bytes have been read. */ void read(uint8 *buffer, uint32 length); /** - * @brief Transmit a byte. - * @param data Byte to transmit. - */ -// void write(uint8 data); - - /** - * @brief Transmit a half word. + * @brief Transmit one byte/word. * @param data to transmit. */ - void write(uint16 data); - + void write(uint16 data); + void write16(uint16 data); // write 2 bytes in 8 bit mode (DFF=0) + /** - * @brief Transmit multiple bytes. - * @param buffer Bytes to transmit. - * @param length Number of bytes in buffer to transmit. + * @brief Transmit one byte/word a specified number of times. + * @param data to transmit. */ - void write(const uint8 *buffer, uint32 length); + void write(uint16 data, uint32 n); + + /** + * @brief Transmit multiple bytes/words. + * @param buffer Bytes/words to transmit. + * @param length Number of bytes/words in buffer to transmit. + */ + void write(const void * buffer, uint32 length); /** * @brief Transmit a byte, then return the next unread byte. @@ -261,9 +290,10 @@ public: */ uint8 transfer(uint8 data) const; uint16_t transfer16(uint16_t data) const; - + /** * @brief Sets up a DMA Transfer for "length" bytes. + * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. * * This function transmits and receives to buffers. * @@ -271,31 +301,25 @@ public: * @param receiveBuf buffer Bytes to save received data. * @param length Number of bytes in buffer to transmit. */ - uint8 dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length); + uint8 dmaTransfer(const void * transmitBuf, void * receiveBuf, uint16 length); + void dmaTransferSet(const void *transmitBuf, void *receiveBuf); + uint8 dmaTransferRepeat(uint16 length); /** - * @brief Sets up a DMA Transmit for bytes. + * @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode. + * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. * - * This function transmits and does not care about the RX fifo. - * - * @param transmitBuf buffer Bytes to transmit, - * @param length Number of bytes in buffer to transmit. - * @param minc Set to use Memory Increment mode, clear to use Circular mode. - */ - uint8 dmaSend(uint8 *transmitBuf, uint16 length, bool minc = 1); - - /** - * @brief Sets up a DMA Transmit for half words. - * SPI PERFIPHERAL MUST BE SET TO 16 BIT MODE BEFORE - * - * This function transmits and does not care about the RX fifo. + * This function only transmits and does not care about the RX fifo. * * @param data buffer half words to transmit, * @param length Number of bytes in buffer to transmit. - * @param minc Set to use Memory Increment mode (default if blank), clear to use Circular mode. + * @param minc Set to use Memory Increment mode, clear to use Circular mode. */ - uint8 dmaSend(uint16 *transmitBuf, uint16 length, bool minc = 1); + uint8 dmaSend(const void * transmitBuf, uint16 length, bool minc = 1); + void dmaSendSet(const void * transmitBuf, bool minc); + uint8 dmaSendRepeat(uint16 length); + uint8 dmaSendAsync(const void * transmitBuf, uint16 length, bool minc = 1); /* * Pin accessors */ @@ -327,23 +351,20 @@ public: * this HardwareSPI instance. */ spi_dev* c_dev(void) { return _currentSetting->spi_d; } - - - spi_dev *dev(){ return _currentSetting->spi_d;} - - /** - * @brief Sets the number of the SPI peripheral to be used by - * this HardwareSPI instance. - * - * @param spi_num Number of the SPI port. 1-2 in low density devices - * or 1-3 in high density devices. - */ - - void setModule(int spi_num) - { - _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed - } + spi_dev *dev(){ return _currentSetting->spi_d;} + + /** + * @brief Sets the number of the SPI peripheral to be used by + * this HardwareSPI instance. + * + * @param spi_num Number of the SPI port. 1-2 in low density devices + * or 1-3 in high density devices. + */ + void setModule(int spi_num) + { + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed + } /* -- The following methods are deprecated --------------------------- */ @@ -376,21 +397,25 @@ public: * @see HardwareSPI::read() */ uint8 recv(void); - + private: -/* - static inline void DMA1_CH3_Event() { - dma1_ch3_Active = 0; -// dma_disable(DMA1, DMA_CH3); -// dma_disable(DMA1, DMA_CH2); - - // To Do. Need to wait for - } -*/ + SPISettings _settings[BOARD_NR_SPI]; SPISettings *_currentSetting; - + void updateSettings(void); + /* + * Functions added for DMA transfers with Callback. + * Experimental. + */ + + void EventCallback(void); + + static void _spi1EventCallback(void); + static void _spi2EventCallback(void); + #if BOARD_NR_SPI >= 3 + static void _spi3EventCallback(void); + #endif /* spi_dev *spi_d; uint8_t _SSPin; diff --git a/STM32F1/libraries/STM32ADC/examples/SingleChannelAtSampleRateCircularBuffer/SingleChannelAtSampleRateCircularBuffer.ino b/STM32F1/libraries/STM32ADC/examples/SingleChannelAtSampleRateCircularBuffer/SingleChannelAtSampleRateCircularBuffer.ino new file mode 100644 index 0000000..e63fe32 --- /dev/null +++ b/STM32F1/libraries/STM32ADC/examples/SingleChannelAtSampleRateCircularBuffer/SingleChannelAtSampleRateCircularBuffer.ino @@ -0,0 +1,87 @@ +#include +#include + +#define pinLED PC13 +#define pinOUT PB0 + +#define _SEND_BY_USB +#ifdef SEND_BY_USB +USBSerial usb; +#endif + +// Channels to be acquired. +// A0 (adc1 channel 1) +uint8 pins = 0; + +#define maxSamples 2000 +uint16_t buffer[maxSamples]; +uint16_t *buffers[2]; +uint8_t bufr; +uint8_t bufw; + +#define sampleFreqKhz 200 +#define samplePeriodus 1000 / sampleFreqKhz +#define ticksPerSecond 2 * sampleFreqKhz * 1000 / maxSamples + + +STM32ADC myADC(ADC1); + + +long ticks; +void TimerIRQ(void) { + ticks++; +} +void DmaIRQ(void) { + digitalWrite(pinOUT, ! digitalRead(pinOUT)); + bufw = (bufw+1)%2; + ticks++; +} + +void setup() { + + pinMode(pinLED, OUTPUT); + pinMode(pinOUT, OUTPUT); + pinMode(pins, INPUT_ANALOG); + + Serial.begin(115200); + Serial.println("START"); + + #ifdef SEND_BY_USB + usb.begin(); + while (!usb.isConnected()) ; + #endif + + ticks = 0; + bufr = 0; + bufw = 0; + buffers[0] = &buffer[0]; + buffers[1] = &buffer[maxSamples/2]; + + Timer3.setPeriod(samplePeriodus); + Timer3.setMasterModeTrGo(TIMER_CR2_MMS_UPDATE); + + myADC.calibrate(); + myADC.setSampleRate(ADC_SMPR_1_5); // ? + myADC.setPins(&pins, 1); + myADC.setDMA(buffer, maxSamples, (DMA_MINC_MODE | DMA_CIRC_MODE | DMA_HALF_TRNS | DMA_TRNS_CMPLT), DmaIRQ); + myADC.setTrigger(ADC_EXT_EV_TIM3_TRGO); + myADC.startConversion(); +} + +void loop() { + + if (bufr!=bufw) { + // process data + + #ifdef SEND_BY_USB + if (usb.isConnected()) usb.write((uint8_t *)buffers[bufr],maxSamples); // send it : (maxSamples /2 )*2 (bytes) + #endif + + bufr = (bufr+1)%2; + } + + if (ticks==ticksPerSecond) { + digitalWrite(pinLED, ! digitalRead(pinLED)); + ticks = 0; + } +} diff --git a/STM32F1/libraries/STM32ADC/src/STM32ADC.h b/STM32F1/libraries/STM32ADC/src/STM32ADC.h index fd0588f..685eeb1 100644 --- a/STM32F1/libraries/STM32ADC/src/STM32ADC.h +++ b/STM32F1/libraries/STM32ADC/src/STM32ADC.h @@ -152,7 +152,7 @@ private: voidFuncPtr _DMA_int; voidFuncPtr _ADC_int; voidFuncPtr _AWD_int; - static const float _AverageSlope = 4.3; // mV/oC //4.0 to 4.6 - static const float _V25 = 1.43; //Volts //1.34 - 1.52 + static constexpr float _AverageSlope = 4.3; // mV/oC //4.0 to 4.6 + static constexpr float _V25 = 1.43; //Volts //1.34 - 1.52 }; diff --git a/STM32F1/libraries/STM32ADC/src/utility/util_adc.c b/STM32F1/libraries/STM32ADC/src/utility/util_adc.c index 5d44939..360b235 100644 --- a/STM32F1/libraries/STM32ADC/src/utility/util_adc.c +++ b/STM32F1/libraries/STM32ADC/src/utility/util_adc.c @@ -45,7 +45,7 @@ void enable_adc_irq(adc_dev* dev) {//ADC1 for now. Enable the reading of the internal variables (Temperature and Vref). */ void enable_internal_reading(adc_dev *dev) { - dev->regs->CR2 |= ADC_CR2_TSEREFE; + dev->regs->CR2 |= ADC_CR2_TSVREFE; } /* @@ -137,8 +137,8 @@ void adc_dma_enable(adc_dev * dev) { bb_peri_set_bit(&dev->regs->CR2, ADC_CR2_DMA_BIT, 1); } -uint8 poll_adc_convert(adc_dev *dev) { - return bb_peri_get_bit(dev->regs->SR, ADC_SR_EOC_BIT); +uint8 poll_adc_convert(adc_dev * dev) { + return bb_peri_get_bit(&dev->regs->SR, ADC_SR_EOC_BIT); } diff --git a/STM32F1/libraries/Serasidis_XPT2046_touch/examples/TouchButtons/TouchButtons.ino b/STM32F1/libraries/Serasidis_XPT2046_touch/examples/TouchButtons/TouchButtons.ino index 5ca9606..c710c6a 100644 --- a/STM32F1/libraries/Serasidis_XPT2046_touch/examples/TouchButtons/TouchButtons.ino +++ b/STM32F1/libraries/Serasidis_XPT2046_touch/examples/TouchButtons/TouchButtons.ino @@ -32,12 +32,12 @@ XPT2046_touch ts(CS_PIN, mySPI); // Chip Select pin, SPI port uint16_t xy[2]; void setup() { - Serial1.begin(9600); - Serial1.println("-------------------------------------------------"); - Serial1.println("XPT2046 touch screen buttons"); - Serial1.println("Copyright (c) 02 Dec 2015 by Vassilis Serasidis"); - Serial1.println("Home: http://www.serasidis.gr"); - Serial1.println("-------------------------------------------------"); + Serial.begin(9600); + Serial.println("-------------------------------------------------"); + Serial.println("XPT2046 touch screen buttons"); + Serial.println("Copyright (c) 02 Dec 2015 by Vassilis Serasidis"); + Serial.println("Home: http://www.serasidis.gr"); + Serial.println("-------------------------------------------------"); ts.begin(); //Begin TouchScreen. ts.setButtonsNumber(COLUMNS, LINES); //Divide the Touch screen area into 4 columns and 2 lines and make them act as buttons. } @@ -46,15 +46,15 @@ void loop() { if(ts.read_XY(xy)){ //If the touch screen is preesed, read the X,Y coordinates and print them on Serial port. uint8_t buttonNumber = ts.getButtonNumber(); if(buttonNumber > 0){ - Serial1.print("Button: "); - Serial1.println(buttonNumber); + Serial.print("Button: "); + Serial.println(buttonNumber); - Serial1.print("X: "); - Serial1.println(xy[0]); //Print X value - Serial1.print("Y: "); - Serial1.println(xy[1]); //Print Y value - Serial1.println(); + Serial.print("X: "); + Serial.println(xy[0]); //Print X value + Serial.print("Y: "); + Serial.println(xy[1]); //Print Y value + Serial.println(); } delay(500); } -} \ No newline at end of file +} diff --git a/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.cpp b/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.cpp index d1b0bdf..f24c67a 100644 --- a/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.cpp +++ b/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.cpp @@ -8,81 +8,97 @@ #include "Arduino.h" #include "XPT2046_touch.h" +XPT2046_touch::XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan) : cs_pin(_cs_pin), my_SPI(_spiChan){ + setOversampling(); + setThreshold(); +} -/****************************************************************************/ - XPT2046_touch::XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan) : cs_pin(_cs_pin), my_SPI(_spiChan){ - } - - -/****************************************************************************/ - - void XPT2046_touch::begin(){ +void XPT2046_touch::begin(){ pinMode(cs_pin, OUTPUT); digitalWrite(cs_pin, HIGH); my_SPI.begin(); - } +} - /****************************************************************************/ +uint16_t XPT2046_touch::gatherSamples(uint8_t command) { + uint32_t sample_sum = 0; + uint16_t samples[MAX_OVERSAMPLING]; - boolean XPT2046_touch::read_XY(uint16_t *xy){ - int z1, z2, tmpH, tmpL; + my_SPI.transfer16(command); // discard first reading after switching MUX + for (int i = 0; i < oversampling; ++i) { + samples[i] = my_SPI.transfer16(command); + sample_sum += samples[i]; + } + int32_t avg = sample_sum / oversampling; + if (oversampling < 3) { + return avg >> 3; + } + + // occasionally, we get a reading that is a _far_ outlier. + // checking for, and removing those improves quality a lot. + uint8_t n = oversampling; + for (int i = 0; i < oversampling; ++i) { + if (abs(avg - samples[i]) > 80) { // NOTE: data is left shifted by 3 at this point. I.e. the test is for 10+ pixels deviation from average + sample_sum -= samples[i]; + --n; + } + } + if (n < 2) return avg >> 3; + else return (sample_sum / n) >> 3; +} + +TS_Point XPT2046_touch::getPoint() { + uint16_t z1, z2; + + my_SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0)); // max clock freq for XPT2046 digitalWrite(cs_pin, LOW); + TS_Point ret; //Check if touch screen is pressed. - SPI.transfer(B10110011); // Z1 - delay(10); - tmpH = (my_SPI.transfer(0) << 5); - tmpL = (my_SPI.transfer(0) >> 3); - z1 = tmpH | tmpL; + my_SPI.transfer(B10110011); // trigger Z1 reading + z1 = my_SPI.transfer16(B11000011) >> 3; // read Z1, and trigger Z2 reading + z2 = my_SPI.transfer16(B10010011) >> 3; // read Z2, and trigger Y reading + ret.z = z1 + 4095 - z2; - SPI.transfer(B11000011); // Z2 - delay(10); - tmpH = (my_SPI.transfer(0) << 5); - tmpL = (my_SPI.transfer(0) >> 3); - z2 = tmpH | tmpL; - - if((z2 - z1) < Z_THRESHOLD){ //If the touch screen is pressed, read the X,Y coordinates from XPT2046. - my_SPI.transfer(B11010011); // X - delay(10); - tmpH = (my_SPI.transfer(0) << 5); - tmpL = (my_SPI.transfer(0) >> 3); - xy[0] = tmpH | tmpL; - - my_SPI.transfer(B10010011); // Y - delay(10); - tmpH = (my_SPI.transfer(0) << 5); - tmpL = (my_SPI.transfer(0) >> 3); - xy[1] = tmpH | tmpL; - digitalWrite(cs_pin, HIGH); - return true; + if(ret.z >= threshold){ //If the touch screen is pressed, read the X,Y coordinates from XPT2046. + ret.x = gatherSamples(B10010011); + ret.y = gatherSamples(B11010011); + } else { + ret.z = 0; } + my_SPI.transfer(B00000000); // enter power saving (and IRQ enable) + digitalWrite(cs_pin, HIGH); - return false; - } - - /****************************************************************************/ - void XPT2046_touch::setButtonsNumber(byte columnButtons, byte rowButtons ){ - _rowButtons = rowButtons; - _columnButtons = columnButtons; - } - - /****************************************************************************/ - uint8_t XPT2046_touch::getButtonNumber(){ + my_SPI.endTransaction(); + return ret; +} + +boolean XPT2046_touch::read_XY(uint16_t *xy) { + TS_Point p = getPoint(); + xy[0] = p.x; + xy[1] = p.y; + return p.z > 0; +} + +////////////////// Buttons //////////////// +void XPT2046_touch::setButtonsNumber(byte columnButtons, byte rowButtons ){ + _rowButtons = rowButtons; + _columnButtons = columnButtons; +} + +uint8_t XPT2046_touch::getButtonNumber(){ uint16_t xy[2]; uint8_t tmp, buttonNum; int div; if(read_XY(xy)){ - - div = (X_MAX + X_MIN) / (_columnButtons + 1); - buttonNum = ((xy[1] / div)); - - div = (Y_MAX + Y_MIN) / _rowButtons; - tmp = ((xy[0] / div)); - - return ((buttonNum * _rowButtons) + tmp + 1); //Return the button number. + div = (X_MAX + X_MIN) / (_columnButtons + 1); + buttonNum = ((xy[1] / div)); + + div = (Y_MAX + Y_MIN) / _rowButtons; + tmp = ((xy[0] / div)); + + return ((buttonNum * _rowButtons) + tmp + 1); //Return the button number. } return 0; //Touch screen is not pressed. - } -/****************************************************************************/ +} diff --git a/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.h b/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.h index 0830162..9fbea6a 100644 --- a/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.h +++ b/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.h @@ -11,7 +11,8 @@ #include #include -#define Z_THRESHOLD 3000 +#define Z_THRESHOLD 3500 // Note: reversed for backwards compatiblity: 4095-x +#define MAX_OVERSAMPLING 32 // Pre-defined touch screen calibration for using the 2.4" ILI9341 LCD #define X_MIN 830 @@ -19,23 +20,54 @@ #define Y_MIN 550 #define Y_MAX 3550 + +class TS_Point { +public: + TS_Point(void) : x(0), y(0), z(0) {} + TS_Point(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {} + bool operator==(TS_Point p) { return ((p.x == x) && (p.y == y) && (p.z == z)); } + bool operator!=(TS_Point p) { return ((p.x != x) || (p.y != y) || (p.z != z)); } + int16_t x, y, z; +}; + /** * */ - -class XPT2046_touch{ +class XPT2046_touch { private: uint8_t cs_pin; SPIClass my_SPI; uint8_t _rowButtons = 1; uint8_t _columnButtons = 1; + uint8_t oversampling; + uint16_t threshold; + uint16_t gatherSamples(uint8_t command); public: - XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan); //Contructor. + /** c'tor. Note that no IRQ pin is supported, here. You can easily do that yourself: + * \code if(digitalRead(irq_pin)) { + * // no press: skip + * } else { + * // _may_ be touched, but not necessarily reach the threshold + * TS_Point p = ts.getPoint(); + * if (p.z > 0) { + * // do something + * } + * } + * \endcode */ + XPT2046_touch(uint8_t _cs_pin, SPIClass _spiChan); //Contructor void begin(); void setButtonsNumber(byte rowButtons, byte columnButtons); + /** Number of samples to average per point 0..32 */ + void setOversampling(uint8_t num_readings = 7) { + oversampling = max(1, min(num_readings, MAX_OVERSAMPLING)); + } + void setThreshold(uint16_t threshold = 4095 - Z_THRESHOLD) { + XPT2046_touch::threshold = threshold; + } uint8_t getButtonNumber(); boolean read_XY(uint16_t *xy); + TS_Point getPoint(); }; #endif diff --git a/STM32F1/libraries/USBComposite/AbsMouse.cpp b/STM32F1/libraries/USBComposite/AbsMouse.cpp new file mode 100644 index 0000000..91a27d0 --- /dev/null +++ b/STM32F1/libraries/USBComposite/AbsMouse.cpp @@ -0,0 +1,56 @@ +#include "USBHID.h" + +//================================================================================ +//================================================================================ +// Mouse + +void HIDAbsMouse::begin(void){ +} + +void HIDAbsMouse::end(void){ +} + +void HIDAbsMouse::click(uint8_t b) +{ + report.wheel = 0; + report.buttons = b; + sendReport(); + report.buttons = 0; + sendReport(); +} + +void HIDAbsMouse::move(int16 x, int16 y, int8 wheel) +{ + report.x = x; + report.y = y; + report.wheel = wheel; + + sendReport(); +} + +void HIDAbsMouse::buttons(uint8_t b) +{ + if (b != report.buttons) + { + report.wheel = 0; + report.buttons = b; + sendReport(); + } +} + +void HIDAbsMouse::press(uint8_t b) +{ + buttons(report.buttons | b); +} + +void HIDAbsMouse::release(uint8_t b) +{ + buttons(report.buttons & ~b); +} + +bool HIDAbsMouse::isPressed(uint8_t b) +{ + if ((b & report.buttons) != 0) + return true; + return false; +} diff --git a/STM32F1/libraries/USBComposite/BootKeyboard.cpp b/STM32F1/libraries/USBComposite/BootKeyboard.cpp new file mode 100644 index 0000000..195f4ac --- /dev/null +++ b/STM32F1/libraries/USBComposite/BootKeyboard.cpp @@ -0,0 +1,7 @@ +#include "USBHID.h" + +//================================================================================ +//================================================================================ +// Keyboard + +HIDKeyboard BootKeyboard(0); diff --git a/STM32F1/libraries/USBComposite/Consumer.cpp b/STM32F1/libraries/USBComposite/Consumer.cpp new file mode 100644 index 0000000..6c896b0 --- /dev/null +++ b/STM32F1/libraries/USBComposite/Consumer.cpp @@ -0,0 +1,13 @@ +#include "USBHID.h" + +void HIDConsumer::begin(void) {} +void HIDConsumer::end(void) {} +void HIDConsumer::press(uint16_t button) { + report.button = button; + sendReport(); +} + +void HIDConsumer::release() { + report.button = 0; + sendReport(); +} diff --git a/STM32F1/libraries/USBComposite/HIDReports.cpp b/STM32F1/libraries/USBComposite/HIDReports.cpp new file mode 100644 index 0000000..bd00b54 --- /dev/null +++ b/STM32F1/libraries/USBComposite/HIDReports.cpp @@ -0,0 +1,14 @@ +#include "USBHID.h" + +#define REPORT(name, ...) \ + static uint8_t raw_ ## name[] = { __VA_ARGS__ }; \ + static const HIDReportDescriptor desc_ ## name = { raw_ ##name, sizeof(raw_ ##name) }; \ + const HIDReportDescriptor* hidReport ## name = & desc_ ## name; + +REPORT(KeyboardMouseJoystick, HID_MOUSE_REPORT_DESCRIPTOR(), HID_KEYBOARD_REPORT_DESCRIPTOR(), HID_JOYSTICK_REPORT_DESCRIPTOR()); +REPORT(KeyboardMouse, HID_MOUSE_REPORT_DESCRIPTOR(), HID_KEYBOARD_REPORT_DESCRIPTOR()); +REPORT(Keyboard, HID_KEYBOARD_REPORT_DESCRIPTOR()); +REPORT(Mouse, HID_MOUSE_REPORT_DESCRIPTOR()); +REPORT(KeyboardJoystick, HID_KEYBOARD_REPORT_DESCRIPTOR(), HID_JOYSTICK_REPORT_DESCRIPTOR()); +REPORT(Joystick, HID_JOYSTICK_REPORT_DESCRIPTOR()); +REPORT(BootKeyboard, HID_BOOT_KEYBOARD_REPORT_DESCRIPTOR()); diff --git a/STM32F1/libraries/USBComposite/Joystick.cpp b/STM32F1/libraries/USBComposite/Joystick.cpp new file mode 100644 index 0000000..969cac5 --- /dev/null +++ b/STM32F1/libraries/USBComposite/Joystick.cpp @@ -0,0 +1,118 @@ +#include "USBHID.h" + +// This code requires gcc on low-endian devices. + +//================================================================================ +//================================================================================ +// Joystick + +void HIDJoystick::begin(void){ +} + +void HIDJoystick::end(void){ +} + +void HIDJoystick::setManualReportMode(bool mode) { + manualReport = mode; +} + +bool HIDJoystick::getManualReportMode() { + return manualReport; +} + +void HIDJoystick::safeSendReport() { + if (!manualReport) { + sendReport(); + } +} + +void HIDJoystick::button(uint8_t button, bool val){ + uint32_t mask = ((uint32_t)1 << (button-1)); + + if (val) { + joyReport.buttons |= mask; + } else { + joyReport.buttons &= ~mask; + } + + safeSendReport(); +} + +void HIDJoystick::X(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.x = val; + + safeSendReport(); +} + +void HIDJoystick::Y(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.y = val; + + safeSendReport(); +} + +void HIDJoystick::position(uint16_t x, uint16_t y){ + if (x > 1023) x = 1023; + if (y > 1023) y = 1023; + joyReport.x = x; + joyReport.y = y; + + safeSendReport(); +} + +void HIDJoystick::Xrotate(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.rx = val; + + safeSendReport(); +} + +void HIDJoystick::Yrotate(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.ry = val; + + safeSendReport(); +} + +void HIDJoystick::sliderLeft(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.sliderLeft = val; + + safeSendReport(); +} + +void HIDJoystick::sliderRight(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.sliderRight = val; + + safeSendReport(); +} + +void HIDJoystick::slider(uint16_t val){ + if (val > 1023) val = 1023; + joyReport.sliderLeft = val; + joyReport.sliderRight = val; + + safeSendReport(); +} + +void HIDJoystick::hat(int16_t dir){ + uint8_t val; + if (dir < 0) val = 15; + else if (dir < 23) val = 0; + else if (dir < 68) val = 1; + else if (dir < 113) val = 2; + else if (dir < 158) val = 3; + else if (dir < 203) val = 4; + else if (dir < 245) val = 5; + else if (dir < 293) val = 6; + else if (dir < 338) val = 7; + else val = 15; + + joyReport.hat = val; + + safeSendReport(); +} + +HIDJoystick Joystick; diff --git a/STM32F1/libraries/USBComposite/Keyboard.cpp b/STM32F1/libraries/USBComposite/Keyboard.cpp new file mode 100644 index 0000000..a658cc5 --- /dev/null +++ b/STM32F1/libraries/USBComposite/Keyboard.cpp @@ -0,0 +1,258 @@ +#include "USBHID.h" +#include + +//================================================================================ +//================================================================================ +// Keyboard + +#define SHIFT 0x80 +static const uint8_t ascii_to_hid[128] = +{ + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e|SHIFT, // ! + 0x34|SHIFT, // " + 0x20|SHIFT, // # + 0x21|SHIFT, // $ + 0x22|SHIFT, // % + 0x24|SHIFT, // & + 0x34, // ' + 0x26|SHIFT, // ( + 0x27|SHIFT, // ) + 0x25|SHIFT, // * + 0x2e|SHIFT, // + + 0x36, // , + 0x2d, // - + 0x37, // . + 0x38, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x33|SHIFT, // : + 0x33, // ; + 0x36|SHIFT, // < + 0x2e, // = + 0x37|SHIFT, // > + 0x38|SHIFT, // ? + 0x1f|SHIFT, // @ + 0x04|SHIFT, // A + 0x05|SHIFT, // B + 0x06|SHIFT, // C + 0x07|SHIFT, // D + 0x08|SHIFT, // E + 0x09|SHIFT, // F + 0x0a|SHIFT, // G + 0x0b|SHIFT, // H + 0x0c|SHIFT, // I + 0x0d|SHIFT, // J + 0x0e|SHIFT, // K + 0x0f|SHIFT, // L + 0x10|SHIFT, // M + 0x11|SHIFT, // N + 0x12|SHIFT, // O + 0x13|SHIFT, // P + 0x14|SHIFT, // Q + 0x15|SHIFT, // R + 0x16|SHIFT, // S + 0x17|SHIFT, // T + 0x18|SHIFT, // U + 0x19|SHIFT, // V + 0x1a|SHIFT, // W + 0x1b|SHIFT, // X + 0x1c|SHIFT, // Y + 0x1d|SHIFT, // Z + 0x2f, // [ + 0x31, // bslash + 0x30, // ] + 0x23|SHIFT, // ^ + 0x2d|SHIFT, // _ + 0x35, // ` + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x2f|SHIFT, // + 0x31|SHIFT, // | + 0x30|SHIFT, // } + 0x35|SHIFT, // ~ + 0 // DEL +}; + +void HIDKeyboard::begin(void){ + USBHID.addOutputBuffer(&ledData); +} + +void HIDKeyboard::end(void) { +} + +// 136: non-printing key +// shift -> 0x02 +// modifiers: 128 --> bit shift + +uint8_t HIDKeyboard::getKeyCode(uint8_t k, uint8_t* modifiersP) +{ + *modifiersP = 0; + + if (adjustForHostCapsLock && (getLEDs() & 0x02)) { // capslock is down on host OS, so host will reverse + if ('a' <= k && k <= 'z') + k += 'A'-'a'; + else if ('A' <= k && k <= 'Z') + k += 'a'-'A'; + } + + if (k < 0x80) { + k = ascii_to_hid[k]; + if (k & SHIFT) { + k &= 0x7f; + *modifiersP = 0x02; + } + return k; + } + if (k >= 0x88) { // non-printing key, Arduino format + return k - 0x88; + } + else { // shift key + *modifiersP = 1<<(k-0x80); + return 0; + } +} + +size_t HIDKeyboard::press(uint8_t k) { + uint8_t modifiers; + + k = getKeyCode(k, &modifiers); + + if (k == 0) { + if (modifiers == 0) { + return 0; + } + } + else { + for (unsigned i = 0; i. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/MidiSpecs.h b/STM32F1/libraries/USBComposite/MidiSpecs.h new file mode 100644 index 0000000..6d2acbe --- /dev/null +++ b/STM32F1/libraries/USBComposite/MidiSpecs.h @@ -0,0 +1,151 @@ +/*--------------------------------------------------------------------------MidiSpecs.h + * + * These defines are based on specs created by the USB and MMA standards organizations. + * There are not a lot of other ways to code them so licensing this is rather ludicrous. + * However, in order to be able to embed this in client projects, and avoid the stupidity + * of enforced open everything I will declare the following about this file. + * + * Copyright (c) 2011 Donald Delmar Davis, Suspect Devices + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * USB midi commands from + * MIDI10.pdf "Universal Serial Bus Device Class Definition for MIDI Devices" + * REV 1. (1999) + * http://www.usb.org/developers/devclass_docs/midi10.pdf + * + */ + +#ifndef __LETS_MIDI_SPECS_H__ +#define __LETS_MIDI_SPECS_H__ +#include +#include +// rework this for the different architectures.... +#if defined(__GNUC__) +typedef struct +{ + unsigned cin : 4; // this is the low nibble. + unsigned cable : 4; +// uint8_t cin; + uint8_t midi0; + uint8_t midi1; + uint8_t midi2; +} __attribute__ ((__packed__)) MIDI_EVENT_PACKET_t ; +#else +typedef struct // may need to be adjusted for other compilers and bitfield order... +{ + unsigned cable : 4; + unsigned cin : 4; + uint8_t midi0; + uint8_t midi1; + uint8_t midi2; +} MIDI_EVENT_PACKET_t ; +#endif + + +#define CIN_MISC_FUNCTION 0x00 /* Reserved for future extension. */ +#define CIN_CABLE_EVENT 0x01 /* Reserved for future extension. */ +#define CIN_2BYTE_SYS_COMMON 0x02 /* 2Bytes -- MTC, SongSelect, etc. */ +#define CIN_3BYTE_SYS_COMMON 0x03 /* 3Bytes -- SPP, etc. */ +#define CIN_SYSEX 0x04 /* 3Bytes */ +#define CIN_SYSEX_ENDS_IN_1 0x05 /* 1Bytes */ +#define CIN_SYSEX_ENDS_IN_2 0x06 /* 2Bytes */ +#define CIN_SYSEX_ENDS_IN_3 0x07 /* 3Bytes */ +#define CIN_NOTE_OFF 0x08 /* 3Bytes */ +#define CIN_NOTE_ON 0x09 /* 3Bytes */ +#define CIN_AFTER_TOUCH 0x0A /* 3Bytes */ +#define CIN_CONTROL_CHANGE 0x0B /* 3Bytes */ +#define CIN_PROGRAM_CHANGE 0x0C /* 2Bytes */ +#define CIN_CHANNEL_PRESSURE 0x0D /* 2Bytes */ +#define CIN_PITCH_WHEEL 0x0E /* 3Bytes */ +#define CIN_1BYTE 0x0F /* 1Bytes */ +//#define CIN_IS_SYSEX(cin) ((cin == CIN_SYSEX)||(cin == CIN_SYSEX_ENDS_IN_1)||(cin == CIN_SYSEX_ENDS_IN_2)||(cin == CIN_SYSEX_ENDS_IN_3)) +#define CIN_IS_SYSEX(cin) ( ((cin) & ~(0x08)) && ((cin) &0x04) ) + +/* + * MIDI V1 message definitions these are from the MMA document + * http://www.midi.org/techspecs/midimessages.php + */ +#define MIDIv1_BAUD_RATE 31250 + +/* + * parse midi (v1) message macros + */ +#define MIDIv1_IS_STATUS(b) ((b) & 0x80) +#define MIDIv1_IS_VOICE(b) ((b) <= 0xEF) +#define MIDIv1_VOICE_COMMAND(b) ((b) & 0xF0) +#define MIDIv1_VOICE_CHANNEL(b) ((b) & 0x0F) +#define MIDIv1_IS_SYSCOMMON(b) (((b) >= 0xF0) & ((b) < 0xF8)) +#define MIDIv1_IS_REALTIME(b) ((b) >= 0xF8) + +/* + * Voice category messages + */ +#define MIDIv1_NOTE_OFF 0x80 /* 2 bytes data -- CIN_NOTE_OFF */ +#define MIDIv1_NOTE_ON 0x90 /* 2 bytes data -- CIN_NOTE_ON */ +#define MIDIv1_AFTER_TOUCH 0xA0 /* 2 bytes data -- CIN_AFTER_TOUCH */ +#define MIDIv1_CONTROL_CHANGE 0xB0 /* 2 bytes data -- CIN_CONTROL_CHANGE */ +#define MIDIv1_PROGRAM_CHANGE 0xC0 /* 1 byte data -- CIN_PROGRAM_CHANGE */ +#define MIDIv1_CHANNEL_PRESSURE 0xD0 /* 1 byte data -- CIN_CHANNEL_PRESSURE */ +#define MIDIv1_PITCH_WHEEL 0xE0 /* 2 bytes data -- CIN_PITCH_WHEEL */ + +/* + * System common category messages + */ +#define MIDIv1_SYSEX_START 0xF0 +#define MIDIv1_SYSEX_END 0xF7 +#define MIDIv1_MTC_QUARTER_FRAME 0xF1 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */ +#define MIDIv1_SONG_POSITION_PTR 0xF2 /* 2 bytes data -- CIN_3BYTE_SYS_COMMON */ +#define MIDIv1_SONG_SELECT 0xF3 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */ +#define MIDIv1_TUNE_REQUEST 0xF6 /* no data -- CIN_1BYTE */ + +/* + * Realtime category messages, can be sent anytime + */ +#define MIDIv1_CLOCK 0xF8 /* no data -- CIN_1BYTE */ +#define MIDIv1_TICK 0xF9 /* no data -- CIN_1BYTE */ +#define MIDIv1_START 0xFA /* no data -- CIN_1BYTE */ +#define MIDIv1_CONTINUE 0xFB /* no data -- CIN_1BYTE */ +#define MIDIv1_STOP 0xFC /* no data -- CIN_1BYTE */ +#define MIDIv1_ACTIVE_SENSE 0xFE /* no data -- CIN_1BYTE */ +#define MIDIv1_RESET 0xFF /* no data -- CIN_1BYTE */ + +/* + * sysex universal id's + */ +#define MIDIv1_UNIVERSAL_REALTIME_ID 0x7F +#define MIDIv1_UNIVERSAL_NON_REALTIME_ID 0x7E +#define MIDIv1_UNIVERSAL_ALL_CHANNELS 0x7F +/* + * Susbset of universal sysex (general info request) + * As described http://www.blitter.com/~russtopia/MIDI/~jglatt/tech/midispec.htm + */ +#define USYSEX_NON_REAL_TIME 0x7E +#define USYSEX_REAL_TIME 0x7F +#define USYSEX_ALL_CHANNELS 0x7F +#define USYSEX_GENERAL_INFO 0x06 +#define USYSEX_GI_ID_REQUEST 0x01 +#define USYSEX_GI_ID_RESPONSE 0x02 + + +#endif + + diff --git a/STM32F1/libraries/USBComposite/MinSysex.c b/STM32F1/libraries/USBComposite/MinSysex.c new file mode 100644 index 0000000..f9a54d3 --- /dev/null +++ b/STM32F1/libraries/USBComposite/MinSysex.c @@ -0,0 +1,306 @@ +// +// MinSysex.c +// LibMaple4Midi +// +// Created by Donald D Davis on 4/11/13. +// Copyright (c) 2013 Suspect Devices. All rights reserved. +// Modified BSD Liscense +/* + 0xF0 SysEx + 0x7E Non-Realtime + 0x7F The SysEx channel. Could be from 0x00 to 0x7F. + Here we set it to "disregard channel". + 0x06 Sub-ID -- General Information + 0x01 Sub-ID2 -- Identity Request + 0xF7 End of SysEx +---- response + 0xF0 SysEx + 0x7E Non-Realtime + 0x7F The SysEx channel. Could be from 0x00 to 0x7F. + Here we set it to "disregard channel". + 0x06 Sub-ID -- General Information + 0x02 Sub-ID2 -- Identity Reply + 0xID Manufacturer's ID + 0xf1 The f1 and f2 bytes make up the family code. Each + 0xf2 manufacturer assigns different family codes to his products. + 0xp1 The p1 and p2 bytes make up the model number. Each + 0xp2 manufacturer assigns different model numbers to his products. + 0xv1 The v1, v2, v3 and v4 bytes make up the version number. + 0xv2 + 0xv3 + 0xv4 + 0xF7 End of SysEx +*/ + +#define USB_MIDI +#ifdef USB_MIDI + +// change this to packets +#define STANDARD_ID_RESPONSE_LENGTH 7 + +#include "usb_midi_device.h" +#include +#include +#include +//#include + + +#define MAX_SYSEX_SIZE 256 + +/********************************* ACHTUNG! ignores usbmidi cable ********************************/ +/*const MIDI_EVENT_PACKET_t standardIDResponse[]={ + { DEFAULT_MIDI_CABLE, + CIN_SYSEX, + MIDIv1_SYSEX_START, + USYSEX_NON_REAL_TIME, + USYSEX_ALL_CHANNELS}, + { DEFAULT_MIDI_CABLE, + CIN_SYSEX, + USYSEX_GENERAL_INFO, + USYSEX_GI_ID_RESPONSE, + LEAFLABS_MMA_VENDOR_1}, + { DEFAULT_MIDI_CABLE, + CIN_SYSEX, + LEAFLABS_MMA_VENDOR_2, // extended ID + LEAFLABS_MMA_VENDOR_3, // extended ID + 1}, // family #1 + { DEFAULT_MIDI_CABLE, + CIN_SYSEX, + 2, // family #2 + 1, // part #1 + 2}, // part #2 + { DEFAULT_MIDI_CABLE, + CIN_SYSEX, + 0, // version 1 + 0, // version 2 + 1}, // version 3 + { DEFAULT_MIDI_CABLE, + CIN_SYSEX_ENDS_IN_2, + '!', // lgl compatible + MIDIv1_SYSEX_END, + 0} +}; +*/ +const uint8 standardIDResponse[]={ + CIN_SYSEX, + MIDIv1_SYSEX_START, + USYSEX_NON_REAL_TIME, + USYSEX_ALL_CHANNELS, + CIN_SYSEX, + USYSEX_GENERAL_INFO, + USYSEX_GI_ID_RESPONSE, + LEAFLABS_MMA_VENDOR_1, + CIN_SYSEX, + LEAFLABS_MMA_VENDOR_2, // extended ID + LEAFLABS_MMA_VENDOR_3, // extended ID + 1, // family #1 + CIN_SYSEX, + 2, // family #2 + 1, // part #1 + 2, // part #2 + CIN_SYSEX, + 0, // version 1 + 0, // version 2 + 1, // version 3 + CIN_SYSEX_ENDS_IN_2, + '!', // lgl compatible + MIDIv1_SYSEX_END, + 0 +}; +//#define STANDARD_ID_RESPONSE_LENGTH (sizeof(standardIDResponse)) + +typedef enum {NOT_IN_SYSEX=0,COULD_BE_MY_SYSEX,YUP_ITS_MY_SYSEX,ITS_NOT_MY_SYSEX} sysexStates; +volatile uint8 sysexBuffer[MAX_SYSEX_SIZE]; +volatile sysexStates sysexState; +volatile int sysexFinger=0; + +/* + 0xF0 SysEx + 0x?? LEAFLABS_MMA_VENDOR_1 + 0x?? LEAFLABS_MMA_VENDOR_2 + + 0x?? LEAFLABS_MMA_VENDOR_3 + 0x10 LGL_DEVICE_NUMBER + 0xLE CMD: REBOOT + + 0xf7 EOSysEx +*/ +#define STACK_TOP 0x20000800 +#define EXC_RETURN 0xFFFFFFF9 +#define DEFAULT_CPSR 0x61000000 +#define RESET_DELAY 100000 +#if 0 +static void wait_reset(void) { + delay_us(RESET_DELAY); + nvic_sys_reset(); +} +#endif + +/* -----------------------------------------------------------------------------dealWithItQuickly() + * Note: at this point we have established that the sysex belongs to us. + * So we need to respond to any generic requests like information requests. + * We also need to handle requests which are meant for us. At the moment this is just the + * reset request. + * + */ +void dealWithItQuickly(){ + switch (sysexBuffer[1]) { + case USYSEX_NON_REAL_TIME: + switch (sysexBuffer[3]) { + case USYSEX_GENERAL_INFO: + if (sysexBuffer[4]==USYSEX_GI_ID_REQUEST) { + usb_midi_tx((uint32 *) standardIDResponse, STANDARD_ID_RESPONSE_LENGTH); + } + } + case USYSEX_REAL_TIME: + break; +#if 0 + case LEAFLABS_MMA_VENDOR_1: + if (sysexBuffer[5]==LGL_RESET_CMD) { + uintptr_t target = (uintptr_t)wait_reset | 0x1; + asm volatile("mov r0, %[stack_top] \n\t" // Reset stack + "mov sp, r0 \n\t" + "mov r0, #1 \n\t" + "mov r1, %[target_addr] \n\t" + "mov r2, %[cpsr] \n\t" + "push {r2} \n\t" // Fake xPSR + "push {r1} \n\t" // PC target addr + "push {r0} \n\t" // Fake LR + "push {r0} \n\t" // Fake R12 + "push {r0} \n\t" // Fake R3 + "push {r0} \n\t" // Fake R2 + "push {r0} \n\t" // Fake R1 + "push {r0} \n\t" // Fake R0 + "mov lr, %[exc_return] \n\t" + "bx lr" + : + : [stack_top] "r" (STACK_TOP), + [target_addr] "r" (target), + [exc_return] "r" (EXC_RETURN), + [cpsr] "r" (DEFAULT_CPSR) + : "r0", "r1", "r2"); + /* Can't happen. */ + ASSERT_FAULT(0); + + } +#endif + default: + break; + } + ;//turn the led on? +} + +/* -----------------------------------------------------------------------------LglSysexHandler() + * The idea here is to identify which Sysex's belong to us and deal with them. + */ +void LglSysexHandler(uint32 *midiBufferRx, uint32 *rx_offset, uint32 *n_unread_packets) { + MIDI_EVENT_PACKET_t * midiPackets = (MIDI_EVENT_PACKET_t *) (midiBufferRx+(*rx_offset)); + uint8 nPackets=((*n_unread_packets)-(*rx_offset)); + int cPacket; + uint8 soPackets=0; + /********************************* ACHTUNG! ignores usbmidi cable ********************************/ + MIDI_EVENT_PACKET_t *packet; + for (cPacket=0;cPacketcin)) { + continue; + } // else { + if (!soPackets) { + soPackets=cPacket*4; + } + if ((sysexState==YUP_ITS_MY_SYSEX) && ((sysexFinger+3)>=MAX_SYSEX_SIZE)){ + sysexState=ITS_NOT_MY_SYSEX; //eisenhower policy. Even if its mine I cant deal with it. + } + switch (packet->cin) { + case CIN_SYSEX: + switch (sysexState) { + case NOT_IN_SYSEX : // new sysex. + sysexFinger=0; + if (packet->midi0 == MIDIv1_SYSEX_START) { + if (packet->midi1==USYSEX_REAL_TIME + ||packet->midi1==USYSEX_NON_REAL_TIME) { + if ((packet->midi2==myMidiChannel) + ||(packet->midi2==USYSEX_ALL_CHANNELS) + ) { + sysexState=YUP_ITS_MY_SYSEX; + sysexBuffer[sysexFinger++]=MIDIv1_SYSEX_START; + sysexBuffer[sysexFinger++]=packet->midi1; + sysexBuffer[sysexFinger++]=packet->midi2; + break; + } + } else if ((packet->midi1==myMidiID[0]) + && (packet->midi2==myMidiID[1]) + ){ + sysexState=COULD_BE_MY_SYSEX; + sysexBuffer[sysexFinger++]=MIDIv1_SYSEX_START; + sysexBuffer[sysexFinger++]=packet->midi1; + sysexBuffer[sysexFinger++]=packet->midi2; + break; + } + } + break; + + case COULD_BE_MY_SYSEX: + if (packet->midi0==myMidiID[2]) { + sysexState=YUP_ITS_MY_SYSEX; + sysexBuffer[sysexFinger++]=packet->midi0; + sysexBuffer[sysexFinger++]=packet->midi1; + sysexBuffer[sysexFinger++]=packet->midi2; + } else { + sysexState=ITS_NOT_MY_SYSEX; + sysexFinger=0; + } + break; + default: + break; + + } + + break; + case CIN_SYSEX_ENDS_IN_1: + case CIN_SYSEX_ENDS_IN_2: + case CIN_SYSEX_ENDS_IN_3: + sysexBuffer[sysexFinger++]=packet->midi0; + sysexBuffer[sysexFinger++]=packet->midi1; + sysexBuffer[sysexFinger++]=packet->midi2; + if (sysexState==YUP_ITS_MY_SYSEX) { + if(cPacket>=(int32)(*n_unread_packets)){ + *n_unread_packets = soPackets; + *rx_offset = soPackets; + } else { + uint8 c = cPacket; + uint32 *s; + uint32 *d = midiBufferRx + soPackets; + for (s = midiBufferRx+c; + ((*n_unread_packets) && (s <= midiBufferRx+(USB_MIDI_RX_EPSIZE/4))); + d++,s++ + ) { + (*d)=(*s); + (*n_unread_packets)--; + (*rx_offset)++; + + } + // we need to reset the for loop variables to re process remaining data. + nPackets=((*n_unread_packets)-(*rx_offset)); + cPacket=(*rx_offset); + } + dealWithItQuickly(); + + } + sysexFinger=0; + sysexState=NOT_IN_SYSEX; + + break; + default: + return; + } + //} + + + + } + // its our sysex and we will cry if we want to + return; +} + +#endif diff --git a/STM32F1/libraries/USBComposite/MinSysex.h b/STM32F1/libraries/USBComposite/MinSysex.h new file mode 100644 index 0000000..958eded --- /dev/null +++ b/STM32F1/libraries/USBComposite/MinSysex.h @@ -0,0 +1,37 @@ +// +// lgl_min_sysex.h +// LibMaple4Midi +// +// Created by Donald D Davis on 4/11/13. +// Copyright (c) 2013 Suspect Devices. All rights reserved. +// + +#ifndef __LGL_MIN_SYSEX_H__ +#define __LGL_MIN_SYSEX_H__ 1 + + +#include "MidiSpecs.h" +//#include "LGL.h" + +#define LEAFLABS_MMA_VENDOR_1 0x7D +#define LEAFLABS_MMA_VENDOR_2 0x1E +#define LEAFLABS_MMA_VENDOR_3 0x4F + +// move to LGL.h +#define LGL_RESET_CMD 0x1e + +#define DEFAULT_MIDI_CHANNEL 0x0A +#define DEFAULT_MIDI_DEVICE 0x0A +#define DEFAULT_MIDI_CABLE 0x00 + +// eventually all of this should be in a place for settings which can be written to flash. +extern volatile uint8 myMidiChannel; +extern volatile uint8 myMidiDevice; +extern volatile uint8 myMidiCable; +extern volatile uint8 myMidiID[]; + + +void LglSysexHandler(uint32 *midiBufferRx,uint32 *rx_offset,uint32 *n_unread_bytes); + +#endif + diff --git a/STM32F1/libraries/USBComposite/Mouse.cpp b/STM32F1/libraries/USBComposite/Mouse.cpp new file mode 100644 index 0000000..2f3abb9 --- /dev/null +++ b/STM32F1/libraries/USBComposite/Mouse.cpp @@ -0,0 +1,57 @@ +#include "USBHID.h" + +//================================================================================ +//================================================================================ +// Mouse + +void HIDMouse::begin(void){ +} + +void HIDMouse::end(void){ +} + +void HIDMouse::click(uint8_t b) +{ + _buttons = b; + move(0,0,0); + _buttons = 0; + move(0,0,0); +} + +void HIDMouse::move(signed char x, signed char y, signed char wheel) +{ + reportBuffer[1] = _buttons; + reportBuffer[2] = x; + reportBuffer[3] = y; + reportBuffer[4] = wheel; + + sendReport(); +} + +void HIDMouse::buttons(uint8_t b) +{ + if (b != _buttons) + { + _buttons = b; + move(0,0,0); + } +} + +void HIDMouse::press(uint8_t b) +{ + buttons(_buttons | b); +} + +void HIDMouse::release(uint8_t b) +{ + buttons(_buttons & ~b); +} + +bool HIDMouse::isPressed(uint8_t b) +{ + if ((b & _buttons) > 0) + return true; + return false; +} + +HIDMouse Mouse; diff --git a/STM32F1/libraries/USBComposite/README.md b/STM32F1/libraries/USBComposite/README.md new file mode 100644 index 0000000..8c80c13 --- /dev/null +++ b/STM32F1/libraries/USBComposite/README.md @@ -0,0 +1,88 @@ +# USB Composite library for STM32F1 + +## Protocols supported + +- standard USB HID, with many built-in profiles, and customizable with more + +- MIDI over USB + +- XBox360 controller (only controller-to-host is currently supported) + +- Mass storage + +## Basic concepts + +Start with: +``` +#include +``` + +The library defines several crucial objects. The central object is: + +``` +extern USBCompositeDevice USBComposite; +``` + +This controls USB device identification as well as registers the plugins that are connected to it. + +Plugin objects included in the library are: + +``` +extern USBHIDDevice USBHID; +extern USBMidi USBMIDI; +extern USBXBox360 XBox360; +extern USBMassStorageDevice MassStorage; +extern USBCompositeSerial CompositeSerial; +``` + +You can also create your own customized instances of these plugin classes or their subclasses. + +If you want to make a simple (non-composite) USB device, you can just call the plugin's `begin()` +method, and it will take care of registering itself with `USBComposite` and starting up +`USBComposite`. If you want to make a composite USB device, however, +you need to control the device with `USBComposite`: + +``` +USBComposite.clear(); // clear any plugins previously registered +plugin1.registerComponent(); +plugin2.registerComponent(); +USBComposite.begin(); +``` + +Of course, you may need to do some further configuring of the plugins or the `USBComposite` device +before the `USBComposite.begin()` call. + +Finally, there are a number of objects that implement particular protocols for the `USBHID` plugin: +``` +extern HIDMouse Mouse; +extern HIDKeyboard Keyboard; +extern HIDJoystick Joystick; +extern HIDKeyboard BootKeyboard; +``` +And you can customize with more. Moreover, the `USBHID` plugin itself allows for compositing +multiple HID profiles, e.g., Mouse / Keyboard / three joysticks. + +Not all combinations will fit within the constraints of the STM32F1 USB system, and not all +combinations will be supported by all operating systems. + +## Simple USB device configuration + +A simple USB device uses a single plugin. You just need to call any setup methods for the plugin +and the `begin()` method for the plugin. For instance, to inject keyboard data, you can do: + +``` +USBHID.begin(HID_KEYBOARD); +``` + +and then call `Keyboard.print("TextToInject")` to inject keyboard data. Some plugin configurations +may require further initialization code or further code that needs to be called inside the Arduino +`loop()` function. + +See the `BootKeyboard`, `midiout` and `x360` example code for this procedure. + +Additionally, for backwards compatibility reasons, the `USBHID` plugin has a convenience +`USBHID_begin_with_serial()` function which works just like `USBHID.begin()` except that it also +composites a `CompositeSerial` plugin. + +However, if you want a USB device using more than one plugin, then you will NOT call the plugin's +`begin()` method. \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/USBComposite.cpp b/STM32F1/libraries/USBComposite/USBComposite.cpp new file mode 100644 index 0000000..b659f11 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBComposite.cpp @@ -0,0 +1,147 @@ +#include "USBComposite.h" + +#define DEFAULT_VENDOR_ID 0x1EAF +#define DEFAULT_PRODUCT_ID 0x0004 + +static char* putSerialNumber(char* out, int nibbles, uint32 id) { + for (int i=0; i>= 4) { + uint8 nibble = id & 0xF; + if (nibble <= 9) + *out++ = nibble + '0'; + else + *out++ = nibble - 10 + 'a'; + } + return out; +} + +const char* getDeviceIDString() { + static char string[80/4+1]; + char* p = string; + + uint32 id = (uint32) *(uint16*) (0x1FFFF7E8+0x02); + p = putSerialNumber(p, 4, id); + + id = *(uint32*) (0x1FFFF7E8+0x04); + p = putSerialNumber(p, 8, id); + + id = *(uint32*) (0x1FFFF7E8+0x08); + p = putSerialNumber(p, 8, id); + + *p = 0; + + return string; +} + +USBCompositeDevice::USBCompositeDevice(void) { + vendorId = 0; + productId = 0; + numParts = 0; + setManufacturerString(NULL); + setProductString(NULL); + setSerialString(DEFAULT_SERIAL_STRING); + iManufacturer[0] = 0; + iProduct[0] = 0; + iSerialNumber[0] = 0; + } + +void USBCompositeDevice::setVendorId(uint16 _vendorId) { + if (_vendorId != 0) + vendorId = _vendorId; + else + vendorId = DEFAULT_VENDOR_ID; +} + +void USBCompositeDevice::setProductId(uint16 _productId) { + if (_productId != 0) + productId = _productId; + else + productId = DEFAULT_PRODUCT_ID; +} + +void setString(uint8* out, const usb_descriptor_string* defaultDescriptor, const char* s, uint32 maxLength) { + if (s == NULL) { + uint8 n = defaultDescriptor->bLength; + uint8 m = USB_DESCRIPTOR_STRING_LEN(maxLength); + if (n > m) + n = m; + memcpy(out, defaultDescriptor, n); + out[0] = n; + } + else { + uint32 n = strlen(s); + if (n > maxLength) + n = maxLength; + out[0] = (uint8)USB_DESCRIPTOR_STRING_LEN(n); + out[1] = USB_DESCRIPTOR_TYPE_STRING; + for (uint32 i=0; i= USB_COMPOSITE_MAX_PARTS) + return false; + parts[i] = part; + init[i] = _init; + stop[i] = _stop; + plugin[i] = _plugin; + if (i >= numParts) + numParts++; + return true; +} + +USBCompositeDevice USBComposite; diff --git a/STM32F1/libraries/USBComposite/USBComposite.h b/STM32F1/libraries/USBComposite/USBComposite.h new file mode 100644 index 0000000..152c3c3 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBComposite.h @@ -0,0 +1,64 @@ +#ifndef _USBCOMPOSITE_H_ +#define _USBCOMPOSITE_H_ + +#include +#include "Stream.h" +#include "usb_generic.h" +//#include + +#include +#include +#include +#include + +#define USB_MAX_PRODUCT_LENGTH 32 +#define USB_MAX_MANUFACTURER_LENGTH 32 +#define USB_MAX_SERIAL_NUMBER_LENGTH 20 + + +// You could use this for a serial number, but you'll be revealing the device ID to the host, +// and hence burning it for cryptographic purposes. +const char* getDeviceIDString(); + +#define USB_COMPOSITE_MAX_PARTS 6 + +class USBCompositeDevice; + +#define DEFAULT_SERIAL_STRING "00000000000000000001" + +typedef bool(*USBPartInitializer)(void*); +typedef void(*USBPartStopper)(void*); + +class USBCompositeDevice { +private: + bool enabled = false; + bool haveSerialNumber = false; + uint8_t iManufacturer[USB_DESCRIPTOR_STRING_LEN(USB_MAX_MANUFACTURER_LENGTH)]; + uint8_t iProduct[USB_DESCRIPTOR_STRING_LEN(USB_MAX_PRODUCT_LENGTH)]; + uint8_t iSerialNumber[USB_DESCRIPTOR_STRING_LEN(USB_MAX_SERIAL_NUMBER_LENGTH)]; + uint16 vendorId; + uint16 productId; + USBCompositePart* parts[USB_COMPOSITE_MAX_PARTS]; + USBPartInitializer init[USB_COMPOSITE_MAX_PARTS]; + USBPartStopper stop[USB_COMPOSITE_MAX_PARTS]; + void* plugin[USB_COMPOSITE_MAX_PARTS]; + uint32 numParts; +public: + USBCompositeDevice(void); + void setVendorId(uint16 vendor=0); + void setProductId(uint16 product=0); + void setManufacturerString(const char* manufacturer=NULL); + void setProductString(const char* product=NULL); + void setSerialString(const char* serialNumber=DEFAULT_SERIAL_STRING); + bool begin(void); + void end(void); + void clear(); + bool isReady() { + return enabled && usb_is_connected(USBLIB) && usb_is_configured(USBLIB); + } + bool add(USBCompositePart* part, void* plugin, USBPartInitializer init = NULL, USBPartStopper stop = NULL); +}; + +extern USBCompositeDevice USBComposite; +#endif + \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/USBCompositeSerial.cpp b/STM32F1/libraries/USBComposite/USBCompositeSerial.cpp new file mode 100644 index 0000000..8fa6c98 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBCompositeSerial.cpp @@ -0,0 +1,274 @@ +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "usb_composite_serial.h" + +#define USB_TIMEOUT 50 + +#if defined(SERIAL_USB) +static void rxHook(unsigned, void*); +static void ifaceSetupHook(unsigned, void*); +#endif + +bool USBCompositeSerial::init(USBCompositeSerial* me) { + (void)me; +#if defined(SERIAL_USB) + composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_RX, rxHook); + composite_cdcacm_set_hooks(USBHID_CDCACM_HOOK_IFACE_SETUP, ifaceSetupHook); +#endif + return true; +} + +void USBCompositeSerial::begin(long speed) { + (void)speed; + if (!enabled) { + USBComposite.clear(); + registerComponent(); + USBComposite.begin(); + enabled = true; + } +} + +void USBCompositeSerial::end() { + if (enabled) { + USBComposite.end(); + enabled = false; + } +} + +size_t USBCompositeSerial::write(uint8 ch) { +size_t n = 0; + this->write(&ch, 1); + return n; +} + +size_t USBCompositeSerial::write(const char *str) { +size_t n = 0; + this->write((const uint8*)str, strlen(str)); + return n; +} + +size_t USBCompositeSerial::write(const uint8 *buf, uint32 len) +{ + size_t n = 0; + + if (!this->isConnected() || !buf) { + return 0; + } + + uint32 txed = 0; + while (txed < len) { + txed += composite_cdcacm_tx((const uint8*)buf + txed, len - txed); + } + + return n; +} + +int USBCompositeSerial::available(void) { + return composite_cdcacm_data_available(); +} + +int USBCompositeSerial::peek(void) +{ + uint8 b; + if (composite_cdcacm_peek(&b, 1)==1) + { + return b; + } + else + { + return -1; + } +} + +bool USBCompositeSerial::registerComponent() { + return USBComposite.add(&usbSerialPart, this, (USBPartInitializer)&USBCompositeSerial::init); +} + +void USBCompositeSerial::flush(void) +{ +/*Roger Clark. Rather slow method. Need to improve this */ + uint8 b; + while(composite_cdcacm_data_available()) + { + this->read(&b, 1); + } + return; +} + +uint32 USBCompositeSerial::read(uint8 * buf, uint32 len) { + uint32 rxed = 0; + while (rxed < len) { + rxed += composite_cdcacm_rx(buf + rxed, len - rxed); + } + + return rxed; +} + +/* Blocks forever until 1 byte is received */ +int USBCompositeSerial::read(void) { + uint8 b; + /* + this->read(&b, 1); + return b; + */ + + if (composite_cdcacm_rx(&b, 1)==0) + { + return -1; + } + else + { + return b; + } +} + +uint8 USBCompositeSerial::pending(void) { + return composite_cdcacm_get_pending(); +} + +uint8 USBCompositeSerial::isConnected(void) { + return usb_is_connected(USBLIB) && usb_is_configured(USBLIB) && composite_cdcacm_get_dtr(); +} + +uint8 USBCompositeSerial::getDTR(void) { + return composite_cdcacm_get_dtr(); +} + +uint8 USBCompositeSerial::getRTS(void) { + return composite_cdcacm_get_rts(); +} + +#if defined(SERIAL_USB) + +enum reset_state_t { + DTR_UNSET, + DTR_HIGH, + DTR_NEGEDGE, + DTR_LOW +}; + +static reset_state_t reset_state = DTR_UNSET; + +static void ifaceSetupHook(unsigned hook, void *requestvp) { + (void)hook; + uint8 request = *(uint8*)requestvp; + + // Ignore requests we're not interested in. + if (request != USBHID_CDCACM_SET_CONTROL_LINE_STATE) { + return; + } + + // We need to see a negative edge on DTR before we start looking + // for the in-band magic reset byte sequence. + uint8 dtr = composite_cdcacm_get_dtr(); + switch (reset_state) { + case DTR_UNSET: + reset_state = dtr ? DTR_HIGH : DTR_LOW; + break; + case DTR_HIGH: + reset_state = dtr ? DTR_HIGH : DTR_NEGEDGE; + break; + case DTR_NEGEDGE: + reset_state = dtr ? DTR_HIGH : DTR_LOW; + break; + case DTR_LOW: + reset_state = dtr ? DTR_HIGH : DTR_LOW; + break; + } + + if ((composite_cdcacm_get_baud() == 1200) && (reset_state == DTR_NEGEDGE)) { + iwdg_init(IWDG_PRE_4, 10); + while (1); + } +} + +#define RESET_DELAY 100000 +static void wait_reset(void) { + delay_us(RESET_DELAY); + nvic_sys_reset(); +} + +#define STACK_TOP 0x20000800 +#define EXC_RETURN 0xFFFFFFF9 +#define DEFAULT_CPSR 0x61000000 +static void rxHook(unsigned hook, void *ignored) { + (void)hook; + (void)ignored; + /* FIXME this is mad buggy; we need a new reset sequence. E.g. NAK + * after each RX means you can't reset if any bytes are waiting. */ + if (reset_state == DTR_NEGEDGE) { + reset_state = DTR_LOW; + + if (composite_cdcacm_data_available() >= 4) { + // The magic reset sequence is "1EAF". + static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; + + uint8 chkBuf[4]; + + // Peek at the waiting bytes, looking for reset sequence, + // bailing on mismatch. + composite_cdcacm_peek_ex(chkBuf, composite_cdcacm_data_available() - 4, 4); + for (unsigned i = 0; i < sizeof(magic); i++) { + if (chkBuf[i] != magic[i]) { + return; + } + } + + // Got the magic sequence -> reset, presumably into the bootloader. + // Return address is wait_reset, but we must set the thumb bit. + uintptr_t target = (uintptr_t)wait_reset | 0x1; + asm volatile("mov r0, %[stack_top] \n\t" // Reset stack + "mov sp, r0 \n\t" + "mov r0, #1 \n\t" + "mov r1, %[target_addr] \n\t" + "mov r2, %[cpsr] \n\t" + "push {r2} \n\t" // Fake xPSR + "push {r1} \n\t" // PC target addr + "push {r0} \n\t" // Fake LR + "push {r0} \n\t" // Fake R12 + "push {r0} \n\t" // Fake R3 + "push {r0} \n\t" // Fake R2 + "push {r0} \n\t" // Fake R1 + "push {r0} \n\t" // Fake R0 + "mov lr, %[exc_return] \n\t" + "bx lr" + : + : [stack_top] "r" (STACK_TOP), + [target_addr] "r" (target), + [exc_return] "r" (EXC_RETURN), + [cpsr] "r" (DEFAULT_CPSR) + : "r0", "r1", "r2"); + + /* Can't happen. */ + ASSERT_FAULT(0); + } + } +} +#endif + + +USBCompositeSerial CompositeSerial; + diff --git a/STM32F1/libraries/USBComposite/USBCompositeSerial.h b/STM32F1/libraries/USBComposite/USBCompositeSerial.h new file mode 100644 index 0000000..80f110a --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBCompositeSerial.h @@ -0,0 +1,40 @@ +#ifndef _COMPOSITE_SERIAL_H_ +#define _COMPOSITE_SERIAL_H_ + +#include "USBComposite.h" +#include "usb_composite_serial.h" + +class USBCompositeSerial : public Stream { +private: + bool enabled = false; +public: + void begin(long speed=9600); + void end(); + static bool init(USBCompositeSerial* me); + bool registerComponent(); + + operator bool() { return true; } // Roger Clark. This is needed because in cardinfo.ino it does if (!Serial) . It seems to be a work around for the Leonardo that we needed to implement just to be compliant with the API + + virtual int available(void);// Changed to virtual + + uint32 read(uint8 * buf, uint32 len); + // uint8 read(void); + + // Roger Clark. added functions to support Arduino 1.0 API + virtual int peek(void); + virtual int read(void); + int availableForWrite(void); + virtual void flush(void); + + size_t write(uint8); + size_t write(const char *str); + size_t write(const uint8*, uint32); + + uint8 getRTS(); + uint8 getDTR(); + uint8 isConnected(); + uint8 pending(); +}; + +extern USBCompositeSerial CompositeSerial; +#endif diff --git a/STM32F1/libraries/USBComposite/USBHID.cpp b/STM32F1/libraries/USBComposite/USBHID.cpp new file mode 100644 index 0000000..ca35396 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBHID.cpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include "USBHID.h" +#include "USBCompositeSerial.h" + +#include +#include +#include +#include "usb_hid.h" +#include "usb_composite_serial.h" +#include "usb_generic.h" +#include +#include +#include + +#include + +/* + * USB HID interface + */ + +bool USBHIDDevice::registerComponent() { + return USBComposite.add(&usbHIDPart, this); +} + +void USBHIDDevice::setReportDescriptor(const uint8_t* report_descriptor, uint16_t report_descriptor_length) { + usb_hid_set_report_descriptor(report_descriptor, report_descriptor_length); +} + +void USBHIDDevice::setReportDescriptor(const HIDReportDescriptor* report) { + setReportDescriptor(report->descriptor, report->length); +} + +void USBHIDDevice::begin(const uint8_t* report_descriptor, uint16_t report_descriptor_length, uint16_t idVendor, uint16_t idProduct, + const char* manufacturer, const char* product, const char* serialNumber) { + + if (enabledHID) + return; + + setReportDescriptor(report_descriptor, report_descriptor_length); + + USBComposite.clear(); + USBComposite.setVendorId(idVendor); + USBComposite.setProductId(idProduct); + USBComposite.setManufacturerString(manufacturer); + USBComposite.setProductString(product); + USBComposite.setSerialString(serialNumber); + registerComponent(); + + USBComposite.begin(); + + enabledHID = true; +} + +void USBHIDDevice::begin(const HIDReportDescriptor* report, uint16_t idVendor, uint16_t idProduct, + const char* manufacturer, const char* product, const char* serialNumber) { + begin(report->descriptor, report->length, idVendor, idProduct, manufacturer, product, serialNumber); +} + +void USBHIDDevice::setBuffers(uint8_t type, volatile HIDBuffer_t* fb, int count) { + usb_hid_set_buffers(type, fb, count); +} + +bool USBHIDDevice::addBuffer(uint8_t type, volatile HIDBuffer_t* buffer) { + return 0 != usb_hid_add_buffer(type, buffer); +} + +void USBHIDDevice::clearBuffers(uint8_t type) { + usb_hid_clear_buffers(type); +} + +void USBHIDDevice::clearBuffers() { + clearBuffers(HID_REPORT_TYPE_OUTPUT); + clearBuffers(HID_REPORT_TYPE_FEATURE); +} + +void USBHIDDevice::end(void){ + if(enabledHID){ + USBComposite.end(); + enabledHID = false; + } +} + +void HIDReporter::sendReport() { +// while (usb_is_transmitting() != 0) { +// } + + unsigned toSend = bufferSize; + uint8* b = buffer; + + while (toSend) { + unsigned delta = usb_hid_tx(b, toSend); + toSend -= delta; + b += delta; + } + +// while (usb_is_transmitting() != 0) { +// } + + /* flush out to avoid having the pc wait for more data */ + usb_hid_tx(NULL, 0); +} + +HIDReporter::HIDReporter(uint8_t* _buffer, unsigned _size, uint8_t _reportID) { + if (_reportID == 0) { + buffer = _buffer+1; + bufferSize = _size-1; + } + else { + buffer = _buffer; + bufferSize = _size; + } + memset(buffer, 0, bufferSize); + reportID = _reportID; + if (_size > 0 && reportID != 0) + buffer[0] = _reportID; +} + +HIDReporter::HIDReporter(uint8_t* _buffer, unsigned _size) { + buffer = _buffer; + bufferSize = _size; + memset(buffer, 0, _size); + reportID = 0; +} + +void HIDReporter::setFeature(uint8_t* in) { + return usb_hid_set_feature(reportID, in); +} + +uint16_t HIDReporter::getData(uint8_t type, uint8_t* out, uint8_t poll) { + return usb_hid_get_data(type, reportID, out, poll); +} + +uint16_t HIDReporter::getFeature(uint8_t* out, uint8_t poll) { + return usb_hid_get_data(HID_REPORT_TYPE_FEATURE, reportID, out, poll); +} + +uint16_t HIDReporter::getOutput(uint8_t* out, uint8_t poll) { + return usb_hid_get_data(HID_REPORT_TYPE_OUTPUT, reportID, out, poll); +} + +USBHIDDevice USBHID; + +void USBHID_begin_with_serial(const uint8_t* report_descriptor, uint16_t report_descriptor_length, uint16_t idVendor, uint16_t idProduct, + const char* manufacturer, const char* product, const char* serialNumber) { + + USBComposite.clear(); + USBComposite.setVendorId(idVendor); + USBComposite.setProductId(idProduct); + USBComposite.setManufacturerString(manufacturer); + USBComposite.setProductString(product); + USBComposite.setSerialString(serialNumber); + + USBHID.setReportDescriptor(report_descriptor, report_descriptor_length); + USBHID.registerComponent(); + + CompositeSerial.registerComponent(); + + USBComposite.begin(); +} + +void USBHID_begin_with_serial(const HIDReportDescriptor* report, uint16_t idVendor, uint16_t idProduct, + const char* manufacturer, const char* product, const char* serialNumber) { + USBHID_begin_with_serial(report->descriptor, report->length, idVendor, idProduct, manufacturer, product, serialNumber); +} + diff --git a/STM32F1/libraries/USBComposite/USBHID.h b/STM32F1/libraries/USBComposite/USBHID.h new file mode 100644 index 0000000..0362f4e --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBHID.h @@ -0,0 +1,608 @@ +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#ifndef _USBHID_H_ +#define _USBHID_H_ + +#include +#include +#include +#include +#include "Stream.h" +#include "usb_hid.h" + +#define USB_HID_MAX_PRODUCT_LENGTH 32 +#define USB_HID_MAX_MANUFACTURER_LENGTH 32 +#define USB_HID_MAX_SERIAL_NUMBER_LENGTH 20 + +#define HID_MOUSE_REPORT_ID 1 +#define HID_KEYBOARD_REPORT_ID 2 +#define HID_CONSUMER_REPORT_ID 3 +#define HID_JOYSTICK_REPORT_ID 20 + +#define HID_KEYBOARD_ROLLOVER 6 + +#define MACRO_GET_ARGUMENT_2(x, y, ...) y +#define MACRO_GET_ARGUMENT_1_WITH_DEFAULT(default, ...) MACRO_GET_ARGUMENT_2(placeholder, ## __VA_ARGS__, default) +#define MACRO_ARGUMENT_2_TO_END(skip, ...) __VA_ARGS__ + +// HIDBuffer_t data buffers must have even memory length because of how PMA transfers work +#define HID_DATA_BUFFER_SIZE(n) (((n)+1)/2*2) + +/* note that featureSize must be 1 less than the buffer size for the feature, + since the latter must include the reportId */ +/* this only works in a collection with a report_id */ +#define HID_FEATURE_REPORT_DESCRIPTOR(dataSize) \ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined Page 1) */ \ + 0x09, 0x01, /* USAGE (Vendor Usage 1) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x95, dataSize, /* REPORT_COUNT (xx) */ \ + 0xB1, 0x02, /* FEATURE (Data,Var,Abs) */ \ + +#define HID_OUTPUT_REPORT_DESCRIPTOR(dataSize) \ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined Page 1) */ \ + 0x09, 0x01, /* USAGE (Vendor Usage 1) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x95, dataSize, /* REPORT_COUNT (32) */ \ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ + +#define HID_CONSUMER_REPORT_DESCRIPTOR(...) \ + 0x05, 0x0C, /* usage page (consumer device) */ \ + 0x09, 0x01, /* usage -- consumer control */ \ + 0xA1, 0x01, /* collection (application) */ \ + 0x85, MACRO_GET_ARGUMENT_1_WITH_DEFAULT(HID_CONSUMER_REPORT_ID, ## __VA_ARGS__), /* REPORT_ID */ \ + 0x15, 0x00, /* logical minimum */ \ + 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ \ + 0x19, 0x00, /* usage minimum (0) */ \ + 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ \ + 0x75, 0x10, /* report size (16) */ \ + 0x95, 0x01, /* report count (1) */ \ + 0x81, 0x00, /* input */ \ + MACRO_ARGUMENT_2_TO_END(__VA_ARGS__) \ + 0xC0 /* end collection */ + +#define HID_MOUSE_REPORT_DESCRIPTOR(...) \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) // 54 */ \ + 0x09, 0x02, /* USAGE (Mouse) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, MACRO_GET_ARGUMENT_1_WITH_DEFAULT(HID_MOUSE_REPORT_ID, ## __VA_ARGS__), /* REPORT_ID */ \ + 0x09, 0x01, /* USAGE (Pointer) */ \ + 0xa1, 0x00, /* COLLECTION (Physical) */ \ + 0x05, 0x09, /* USAGE_PAGE (Button) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ + 0x09, 0x30, /* USAGE (X) */ \ + 0x09, 0x31, /* USAGE (Y) */ \ + 0x09, 0x38, /* USAGE (Wheel) */ \ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ \ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x95, 0x03, /* REPORT_COUNT (3) */ \ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ \ + 0xc0, /* END_COLLECTION */ \ + MACRO_ARGUMENT_2_TO_END(__VA_ARGS__) \ + 0xc0 /* END_COLLECTION */ + +#define HID_ABS_MOUSE_REPORT_DESCRIPTOR(...) \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) // 54 */ \ + 0x09, 0x02, /* USAGE (Mouse) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, MACRO_GET_ARGUMENT_1_WITH_DEFAULT(HID_MOUSE_REPORT_ID, ## __VA_ARGS__), /* REPORT_ID */ \ + 0x09, 0x01, /* USAGE (Pointer) */ \ + 0xa1, 0x00, /* COLLECTION (Physical) */ \ + 0x05, 0x09, /* USAGE_PAGE (Button) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ + 0x09, 0x30, /* USAGE (X) */ \ + 0x09, 0x31, /* USAGE (Y) */ \ + 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ \ + 0x26, 0xFF, 0x7f, /* LOGICAL_MAXIMUM (32767) */ \ + 0x75, 0x10, /* REPORT_SIZE (16) */ \ + 0x95, 0x02, /* REPORT_COUNT (2) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + 0x09, 0x38, /* USAGE (Wheel) */ \ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ \ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ \ + 0xc0, /* END_COLLECTION */ \ + MACRO_ARGUMENT_2_TO_END(__VA_ARGS__) \ + 0xc0 /* END_COLLECTION */ + +#define HID_KEYBOARD_REPORT_DESCRIPTOR(...) \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) // 47 */ \ + 0x09, 0x06, /* USAGE (Keyboard) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, MACRO_GET_ARGUMENT_1_WITH_DEFAULT(HID_KEYBOARD_REPORT_ID, ## __VA_ARGS__), /* REPORT_ID */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ \ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +\ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ +\ + 0x95, HID_KEYBOARD_ROLLOVER, /* REPORT_COUNT (6) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ +\ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ \ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ +\ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ + 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ + MACRO_ARGUMENT_2_TO_END(__VA_ARGS__) \ + 0xc0 /* END_COLLECTION */ + +#define HID_BOOT_KEYBOARD_REPORT_DESCRIPTOR(...) \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) // 47 */ \ + 0x09, 0x06, /* USAGE (Keyboard) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ \ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +\ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ +\ + 0x95, 0x06, /* REPORT_COUNT (6) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ +\ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ \ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ +\ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ + 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ + __VA_ARGS__ \ + 0xc0 /* END_COLLECTION */ + +#define HID_JOYSTICK_REPORT_DESCRIPTOR(...) \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x04, /* Usage (Joystick) */ \ + 0xA1, 0x01, /* Collection (Application) */ \ + 0x85, MACRO_GET_ARGUMENT_1_WITH_DEFAULT(HID_JOYSTICK_REPORT_ID, ## __VA_ARGS__), /* REPORT_ID */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x20, /* Report Count (32) */ \ + 0x05, 0x09, /* Usage Page (Button) */ \ + 0x19, 0x01, /* Usage Minimum (Button #1) */ \ + 0x29, 0x20, /* Usage Maximum (Button #32) */ \ + 0x81, 0x02, /* Input (variable,absolute) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x07, /* Logical Maximum (7) */ \ + 0x35, 0x00, /* Physical Minimum (0) */ \ + 0x46, 0x3B, 0x01, /* Physical Maximum (315) */ \ + 0x75, 0x04, /* Report Size (4) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x65, 0x14, /* Unit (20) */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x39, /* Usage (Hat switch) */ \ + 0x81, 0x42, /* Input (variable,absolute,null_state) */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x01, /* Usage (Pointer) */ \ + 0xA1, 0x00, /* Collection () */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023) */ \ + 0x75, 0x0A, /* Report Size (10) */ \ + 0x95, 0x04, /* Report Count (4) */ \ + 0x09, 0x30, /* Usage (X) */ \ + 0x09, 0x31, /* Usage (Y) */ \ + 0x09, 0x33, /* Usage (Rx) */ \ + 0x09, 0x34, /* Usage (Ry) */ \ + 0x81, 0x02, /* Input (variable,absolute) */ \ + 0xC0, /* End Collection */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023) */ \ + 0x75, 0x0A, /* Report Size (10) */ \ + 0x95, 0x02, /* Report Count (2) */ \ + 0x09, 0x36, /* Usage (Slider) */ \ + 0x09, 0x36, /* Usage (Slider) */ \ + 0x81, 0x02, /* Input (variable,absolute) */ \ + MACRO_ARGUMENT_2_TO_END(__VA_ARGS__) \ + 0xC0 + +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + +#define LSB(x) ((x) & 0xFF) +#define MSB(x) (((x) & 0xFF00) >> 8) +// TODO: make this work for txSize > 255 +#define HID_RAW_REPORT_DESCRIPTOR(txSize, rxSize) \ + 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), \ + 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), \ + 0xA1, 0x01, /* Collection 0x01 */ \ +/* 0x85, 10, */ /* REPORT_ID (1) */ \ + 0x75, 0x08, /* report size = 8 bits */ \ + 0x15, 0x00, /* logical minimum = 0 */ \ + 0x26, 0xFF, 0x00, /* logical maximum = 255 */ \ +\ + 0x96, LSB(txSize), MSB(txSize), /* report count TX */ \ + 0x09, 0x01, /* usage */ \ + 0x81, 0x02, /* Input (array) */ \ +\ + 0x75, 0x08, /* report size = 8 bits */ \ + 0x15, 0x00, /* logical minimum = 0 */ \ + 0x26, 0xFF, 0x00, /* logical maximum = 255 */ \ + 0x96, LSB(rxSize), MSB(rxSize), /* report count RX */ \ + 0x09, 0x02, /* usage */ \ + 0x91, 0x02, /* OUTPUT (0x91) */ \ + 0xC0 /* end collection */ + +typedef struct { + uint8_t* descriptor; + uint16_t length; +} HIDReportDescriptor; + +class USBHIDDevice { +private: + bool enabledHID = false; +public: + bool registerComponent(); + void setReportDescriptor(const uint8_t* report_descriptor, uint16_t report_descriptor_length); + void setReportDescriptor(const HIDReportDescriptor* reportDescriptor); + // All the strings are zero-terminated ASCII strings. Use NULL for defaults. + void begin(const uint8_t* report_descriptor, uint16_t length, uint16_t idVendor=0, uint16_t idProduct=0, + const char* manufacturer=NULL, const char* product=NULL, const char* serialNumber="00000000000000000001"); + void begin(const HIDReportDescriptor* reportDescriptor, uint16_t idVendor=0, uint16_t idProduct=0, + const char* manufacturer=NULL, const char* product=NULL, const char* serialNumber="00000000000000000001"); + void setSerial(uint8 serialSupport=true); + void setBuffers(uint8_t buffers, volatile HIDBuffer_t* fb=NULL, int count=0); // type = HID_REPORT_TYPE_FEATURE or HID_REPORT_TYPE_OUTPUT + bool addBuffer(uint8_t type, volatile HIDBuffer_t* buffer); + void clearBuffers(uint8_t type); + void clearBuffers(); + inline bool addFeatureBuffer(volatile HIDBuffer_t* buffer) { + return addBuffer(HID_REPORT_TYPE_FEATURE, buffer); + } + inline bool addOutputBuffer(volatile HIDBuffer_t* buffer) { + return addBuffer(HID_REPORT_TYPE_OUTPUT, buffer); + } + inline void setFeatureBuffers(volatile HIDBuffer_t* fb=NULL, int count=0) { + setBuffers(HID_REPORT_TYPE_FEATURE, fb, count); + } + inline void setOutputBuffers(volatile HIDBuffer_t* fb=NULL, int count=0) { + setBuffers(HID_REPORT_TYPE_OUTPUT, fb, count); + } + void end(void); +}; + +void USBHID_begin_with_serial(const uint8_t* report_descriptor, uint16_t length, uint16_t idVendor=0, uint16_t idProduct=0, + const char* manufacturer=NULL, const char* product=NULL, const char* serialNumber="00000000000000000001"); +void USBHID_begin_with_serial(const HIDReportDescriptor* reportDescriptor, uint16_t idVendor=0, uint16_t idProduct=0, + const char* manufacturer=NULL, const char* product=NULL, const char* serialNumber="00000000000000000001"); + +class HIDReporter { + private: + uint8_t* buffer; + unsigned bufferSize; + uint8_t reportID; + + public: + void sendReport(); + + public: + // if you use this init function, the buffer starts with a reportID, even if the reportID is zero, + // and bufferSize includes the reportID; if reportID is zero, sendReport() will skip the initial + // reportID byte + HIDReporter(uint8_t* _buffer, unsigned _size, uint8_t _reportID); + // if you use this init function, the buffer has no reportID byte in it + HIDReporter(uint8_t* _buffer, unsigned _size); + uint16_t getFeature(uint8_t* out=NULL, uint8_t poll=1); + uint16_t getOutput(uint8_t* out=NULL, uint8_t poll=1); + uint16_t getData(uint8_t type, uint8_t* out, uint8_t poll=1); // type = HID_REPORT_TYPE_FEATURE or HID_REPORT_TYPE_OUTPUT + void setFeature(uint8_t* feature); +}; + +//================================================================================ +//================================================================================ +// Mouse + +#define MOUSE_LEFT 1 +#define MOUSE_RIGHT 2 +#define MOUSE_MIDDLE 4 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) + +class HIDMouse : public HIDReporter { +protected: + uint8_t _buttons; + void buttons(uint8_t b); + uint8_t reportBuffer[5]; +public: + HIDMouse(uint8_t reportID=HID_MOUSE_REPORT_ID) : HIDReporter(reportBuffer, sizeof(reportBuffer), reportID), _buttons(0) {} + void begin(void); + void end(void); + void click(uint8_t b = MOUSE_LEFT); + void move(signed char x, signed char y, signed char wheel = 0); + void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default +}; + +typedef struct { + uint8_t reportID; + uint8_t buttons; + int16_t x; + int16_t y; + uint8_t wheel; +} __packed AbsMouseReport_t; + +class HIDAbsMouse : public HIDReporter { +protected: + void buttons(uint8_t b); + AbsMouseReport_t report; +public: + HIDAbsMouse(uint8_t reportID=HID_MOUSE_REPORT_ID) : HIDReporter((uint8_t*)&report, sizeof(report), reportID) { + report.buttons = 0; + report.x = 0; + report.y = 0; + report.wheel = 0; + } + void begin(void); + void end(void); + void click(uint8_t b = MOUSE_LEFT); + void move(int16_t x, int16_t y, int8_t wheel = 0); + void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default +}; + +typedef struct { + uint8_t reportID; + uint16_t button; +} __packed ConsumerReport_t; + +class HIDConsumer : public HIDReporter { +protected: + ConsumerReport_t report; +public: + enum { + BRIGHTNESS_UP = 0x6F, + BRIGHTNESS_DOWN = 0x70, + VOLUME_UP = 0xE9, + VOLUME_DOWN = 0xEA, + MUTE = 0xE2, + PLAY_OR_PAUSE = 0xCD + // see pages 75ff of http://www.usb.org/developers/hidpage/Hut1_12v2.pdf + }; + HIDConsumer(uint8_t reportID=HID_CONSUMER_REPORT_ID) : HIDReporter((uint8_t*)&report, sizeof(report), reportID) { + report.button = 0; + } + void begin(void); + void end(void); + void press(uint16_t button); + void release(); +}; + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 + +#define KEY_UP_ARROW 0xDA +#define KEY_DOWN_ARROW 0xD9 +#define KEY_LEFT_ARROW 0xD8 +#define KEY_RIGHT_ARROW 0xD7 +#define KEY_BACKSPACE 0xB2 +#define KEY_TAB 0xB3 +#define KEY_RETURN 0xB0 +#define KEY_ESC 0xB1 +#define KEY_INSERT 0xD1 +#define KEY_DELETE 0xD4 +#define KEY_PAGE_UP 0xD3 +#define KEY_PAGE_DOWN 0xD6 +#define KEY_HOME 0xD2 +#define KEY_END 0xD5 +#define KEY_CAPS_LOCK 0xC1 +#define KEY_F1 0xC2 +#define KEY_F2 0xC3 +#define KEY_F3 0xC4 +#define KEY_F4 0xC5 +#define KEY_F5 0xC6 +#define KEY_F6 0xC7 +#define KEY_F7 0xC8 +#define KEY_F8 0xC9 +#define KEY_F9 0xCA +#define KEY_F10 0xCB +#define KEY_F11 0xCC +#define KEY_F12 0xCD + +typedef struct{ + uint8_t reportID; + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[HID_KEYBOARD_ROLLOVER]; +} __packed KeyReport_t; + +class HIDKeyboard : public Print, public HIDReporter { +public: + KeyReport_t keyReport; + +protected: + uint8_t leds[HID_BUFFER_ALLOCATE_SIZE(1,1)]; + HIDBuffer_t ledData; + uint8_t reportID; + uint8_t getKeyCode(uint8_t k, uint8_t* modifiersP); + bool adjustForHostCapsLock = true; + +public: + HIDKeyboard(uint8_t _reportID=HID_KEYBOARD_REPORT_ID) : + HIDReporter((uint8*)&keyReport, sizeof(KeyReport_t), _reportID), + ledData(leds, HID_BUFFER_SIZE(1,_reportID), _reportID, HID_BUFFER_MODE_NO_WAIT), + reportID(_reportID) + {} + void begin(void); + void end(void); + void setAdjustForHostCapsLock(bool state) { + adjustForHostCapsLock = state; + } + inline uint8 getLEDs(void) { + return leds[reportID != 0 ? 1 : 0]; + } + virtual size_t write(uint8_t k); + virtual size_t press(uint8_t k); + virtual size_t release(uint8_t k); + virtual void releaseAll(void); +}; + + +//================================================================================ +//================================================================================ +// Joystick + +// only works for little-endian machines, but makes the code so much more +// readable +typedef struct { + uint8_t reportID; + uint32_t buttons; + unsigned hat:4; + unsigned x:10; + unsigned y:10; + unsigned rx:10; + unsigned ry:10; + unsigned sliderLeft:10; + unsigned sliderRight:10; +} __packed JoystickReport_t; + +static_assert(sizeof(JoystickReport_t)==13, "Wrong endianness/packing!"); + +class HIDJoystick : public HIDReporter { +protected: + JoystickReport_t joyReport; + bool manualReport = false; + void safeSendReport(void); +public: + inline void send(void) { + sendReport(); + } + void setManualReportMode(bool manualReport); // in manual report mode, reports only sent when send() is called + bool getManualReportMode(); + void begin(void); + void end(void); + void button(uint8_t button, bool val); + void X(uint16_t val); + void Y(uint16_t val); + void position(uint16_t x, uint16_t y); + void Xrotate(uint16_t val); + void Yrotate(uint16_t val); + void sliderLeft(uint16_t val); + void sliderRight(uint16_t val); + void slider(uint16_t val); + void hat(int16_t dir); + HIDJoystick(uint8_t reportID=HID_JOYSTICK_REPORT_ID) : HIDReporter((uint8_t*)&joyReport, sizeof(joyReport), reportID) { + joyReport.buttons = 0; + joyReport.hat = 15; + joyReport.x = 512; + joyReport.y = 512; + joyReport.rx = 512; + joyReport.ry = 512; + joyReport.sliderLeft = 0; + joyReport.sliderRight = 0; + } +}; + +extern USBHIDDevice USBHID; + +templateclass HIDRaw : public HIDReporter { +private: + uint8_t txBuffer[txSize]; + uint8_t rxBuffer[HID_BUFFER_ALLOCATE_SIZE(rxSize,0)]; + HIDBuffer_t buf; +public: + HIDRaw() : HIDReporter(txBuffer, sizeof(txBuffer)) {} + void begin(void) { + buf.buffer = rxBuffer; + buf.bufferSize = HID_BUFFER_SIZE(rxSize,0); + buf.reportID = 0; + USBHID.addOutputBuffer(&buf); + } + void end(void); + void send(const uint8_t* data, unsigned n=sizeof(txBuffer)) { + memset(txBuffer, 0, sizeof(txBuffer)); + memcpy(txBuffer, data, n>sizeof(txBuffer)?sizeof(txBuffer):n); + sendReport(); + } +}; + +extern HIDMouse Mouse; +extern HIDKeyboard Keyboard; +extern HIDJoystick Joystick; +extern HIDKeyboard BootKeyboard; + +extern const HIDReportDescriptor* hidReportMouse; +extern const HIDReportDescriptor* hidReportKeyboard; +extern const HIDReportDescriptor* hidReportJoystick; +extern const HIDReportDescriptor* hidReportKeyboardMouse; +extern const HIDReportDescriptor* hidReportKeyboardJoystick; +extern const HIDReportDescriptor* hidReportKeyboardMouseJoystick; +extern const HIDReportDescriptor* hidReportBootKeyboard; + +#define HID_MOUSE hidReportMouse +#define HID_KEYBOARD hidReportKeyboard +#define HID_JOYSTICK hidReportJoystick +#define HID_KEYBOARD_MOUSE hidReportKeyboardMouse +#define HID_KEYBOARD_JOYSTICK hidReportKeyboardJoystick +#define HID_KEYBOARD_MOUSE_JOYSTICK hidReportKeyboardMouseJoystick +#define HID_BOOT_KEYBOARD hidReportBootKeyboard + +#endif + \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/USBMIDI.cpp b/STM32F1/libraries/USBComposite/USBMIDI.cpp new file mode 100644 index 0000000..ba0e895 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBMIDI.cpp @@ -0,0 +1,469 @@ +/****************************************************************************** + * This started out as a munging of Tymm Twillman's arduino Midi Library into the Libusb class, + * though by now very little of the original code is left, except for the class API and + * comments. Tymm Twillman kindly gave Alexander Pruss permission to relicense his code under the MIT + * license, which fixed a nasty licensing mess. + * + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2013 Magnus Lundin. + * Copyright (c) 2013 Donald Delmar Davis, Suspect Devices. + * (c) 2003-2008 Tymm Twillman + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + *****************************************************************************/ + +/** + * @brief USB MIDI device with a class compatible with maplemidi + */ + +#include "USBMIDI.h" + +#include +#include +#include +#include +#include "usb_midi_device.h" +#include +#include "usb_generic.h" + + +/* + * USBMidi interface + */ + +#define USB_TIMEOUT 50 + +void USBMidi::setChannel(unsigned int channel) { + channelIn_ = channel; + +} + +/*bool USBMidi::init(USBMidi* me) { + return true; +}*/ + +bool USBMidi::registerComponent() { + return USBComposite.add(&usbMIDIPart, this); +} + +void USBMidi::begin(unsigned channel) { + setChannel(channel); + + if (enabled) + return; + + USBComposite.clear(); + registerComponent(); + USBComposite.begin(); + + enabled = true; +} + +void USBMidi::end(void) { + if (enabled) { + USBComposite.end(); + enabled = false; + } +} + +void USBMidi::writePacket(uint32 p) { + this->writePackets(&p, 1); +} + +void USBMidi::writePackets(const void *buf, uint32 len) { + if (!this->isConnected() || !buf) { + return; + } + + uint32 txed = 0; + uint32 old_txed = 0; + uint32 start = millis(); + + uint32 sent = 0; + + while (txed < len && (millis() - start < USB_TIMEOUT)) { + sent = usb_midi_tx((const uint32*)buf + txed, len - txed); + txed += sent; + if (old_txed != txed) { + start = millis(); + } + old_txed = txed; + } + + + if (sent == USB_MIDI_TX_EPSIZE) { + while (usb_midi_is_transmitting() != 0) { + } + /* flush out to avoid having the pc wait for more data */ + usb_midi_tx(NULL, 0); + } +} + +uint32 USBMidi::available(void) { + return usb_midi_data_available(); +} + +uint32 USBMidi::readPackets(void *buf, uint32 len) { + if (!buf) { + return 0; + } + + uint32 rxed = 0; + while (rxed < len) { + rxed += usb_midi_rx((uint32*)buf + rxed, len - rxed); + } + + return rxed; +} + +/* Blocks forever until 1 byte is received */ +uint32 USBMidi::readPacket(void) { + uint32 p; + this->readPackets(&p, 1); + return p; +} + +uint8 USBMidi::pending(void) { + return usb_midi_get_pending(); +} + +uint8 USBMidi::isConnected(void) { + return usb_is_connected(USBLIB) && usb_is_configured(USBLIB); +} + + +USBMidi USBMIDI; + + +// These are midi status message types are defined in MidiSpec.h + +union EVENT_t { + uint32 i; + uint8 b[4]; + MIDI_EVENT_PACKET_t p; +}; + +// Handle decoding incoming MIDI traffic a word at a time -- remembers +// what it needs to from one call to the next. +// +// This is a private function & not meant to be called from outside this class. +// It's used whenever data is available from the USB port. +// +void USBMidi::dispatchPacket(uint32 p) +{ + union EVENT_t e; + + e.i=p; + + switch (e.p.cin) { + case CIN_3BYTE_SYS_COMMON: + if (e.p.midi0 == MIDIv1_SONG_POSITION_PTR) { + handleSongPosition(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1)); + } + break; + + case CIN_2BYTE_SYS_COMMON: + switch (e.p.midi0) { + case MIDIv1_SONG_SELECT: + handleSongSelect(e.p.midi1); + break; + case MIDIv1_MTC_QUARTER_FRAME: + // reference library doesnt handle quarter frame. + break; + } + break; + case CIN_NOTE_OFF: + handleNoteOff(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2); + break; + case CIN_NOTE_ON: + handleNoteOn(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2); + break; + case CIN_AFTER_TOUCH: + handleVelocityChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2); + break; + case CIN_CONTROL_CHANGE: + handleControlChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2); + break; + case CIN_PROGRAM_CHANGE: + handleProgramChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1); + break; + case CIN_CHANNEL_PRESSURE: + handleAfterTouch(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1); + break; + + case CIN_PITCH_WHEEL: + handlePitchChange(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1)); + break; + case CIN_1BYTE: + switch (e.p.midi0) { + case MIDIv1_CLOCK: + handleSync(); + break; + case MIDIv1_TICK: + break; + case MIDIv1_START: + handleStart(); + break; + case MIDIv1_CONTINUE: + handleContinue(); + break; + case MIDIv1_STOP: + handleStop(); + break; + case MIDIv1_ACTIVE_SENSE: + handleActiveSense(); + break; + case MIDIv1_RESET: + handleReset(); + break; + case MIDIv1_TUNE_REQUEST: + handleTuneRequest(); + break; + + default: + break; + } + break; + } +} + + +// Try to read data from USB port & pass anything read to processing function +void USBMidi::poll(void) +{ while(available()) { + dispatchPacket(readPacket()); + } +} + +static union EVENT_t outPacket; // since we only use one at a time no point in reallocating it + +// Send Midi NOTE OFF message to a given channel, with note 0-127 and velocity 0-127 +void USBMidi::sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_NOTE_OFF; + outPacket.p.midi0=MIDIv1_NOTE_OFF|(channel & 0x0f); + outPacket.p.midi1=note; + outPacket.p.midi2=velocity; + writePacket(outPacket.i); + +} + + +// Send Midi NOTE ON message to a given channel, with note 0-127 and velocity 0-127 +void USBMidi::sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_NOTE_ON; + outPacket.p.midi0=MIDIv1_NOTE_ON|(channel & 0x0f); + outPacket.p.midi1=note; + outPacket.p.midi2=velocity; + writePacket(outPacket.i); + +} + +// Send a Midi VELOCITY CHANGE message to a given channel, with given note 0-127, +// and new velocity 0-127 +// Note velocity change == polyphonic aftertouch. +// Note aftertouch == channel pressure. +void USBMidi::sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_AFTER_TOUCH; + outPacket.p.midi0=MIDIv1_AFTER_TOUCH |(channel & 0x0f); + outPacket.p.midi1=note; + outPacket.p.midi2=velocity; + writePacket(outPacket.i); + +} + + +// Send a Midi CC message to a given channel, as a given controller 0-127, with given +// value 0-127 +void USBMidi::sendControlChange(unsigned int channel, unsigned int controller, unsigned int value) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_CONTROL_CHANGE; + outPacket.p.midi0=MIDIv1_CONTROL_CHANGE |(channel & 0x0f); + outPacket.p.midi1=controller; + outPacket.p.midi2=value; + writePacket(outPacket.i); + +} + +// Send a Midi PROGRAM CHANGE message to given channel, with program ID 0-127 +void USBMidi::sendProgramChange(unsigned int channel, unsigned int program) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_PROGRAM_CHANGE; + outPacket.p.midi0=MIDIv1_PROGRAM_CHANGE |(channel & 0x0f); + outPacket.p.midi1=program; + writePacket(outPacket.i); + +} + +// Send a Midi AFTER TOUCH message to given channel, with velocity 0-127 +void USBMidi::sendAfterTouch(unsigned int channel, unsigned int velocity) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_CHANNEL_PRESSURE; + outPacket.p.midi0=MIDIv1_CHANNEL_PRESSURE |(channel & 0x0f); + outPacket.p.midi1=velocity; + writePacket(outPacket.i); + +} + +// Send a Midi PITCH CHANGE message, with a 14-bit pitch (always for all channels) +void USBMidi::sendPitchChange(unsigned int pitch) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_PITCH_WHEEL; + outPacket.p.midi0=MIDIv1_PITCH_WHEEL; + outPacket.p.midi1= (uint8) pitch & 0x07F; + outPacket.p.midi2= (uint8) (pitch>>7) & 0x7f; + writePacket(outPacket.i); + +} + +// Send a Midi SONG POSITION message, with a 14-bit position (always for all channels) +void USBMidi::sendSongPosition(unsigned int position) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_3BYTE_SYS_COMMON; + outPacket.p.midi0=MIDIv1_SONG_POSITION_PTR; + outPacket.p.midi1= (uint8) position & 0x07F; + outPacket.p.midi2= (uint8) (position>>7) & 0x7f; + writePacket(outPacket.i); + +} + +// Send a Midi SONG SELECT message, with a song ID of 0-127 (always for all channels) +void USBMidi::sendSongSelect(unsigned int song) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_2BYTE_SYS_COMMON; + outPacket.p.midi0=MIDIv1_SONG_SELECT; + outPacket.p.midi1= (uint8) song & 0x07F; + writePacket(outPacket.i); + +} + +// Send a Midi TUNE REQUEST message (TUNE REQUEST is always for all channels) +void USBMidi::sendTuneRequest(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_TUNE_REQUEST; + writePacket(outPacket.i); +} + + +// Send a Midi SYNC message (SYNC is always for all channels) +void USBMidi::sendSync(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_CLOCK; + writePacket(outPacket.i); +} + +// Send a Midi START message (START is always for all channels) +void USBMidi::sendStart(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_START ; + writePacket(outPacket.i); +} + + +// Send a Midi CONTINUE message (CONTINUE is always for all channels) +void USBMidi::sendContinue(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_CONTINUE ; + writePacket(outPacket.i); +} + + +// Send a Midi STOP message (STOP is always for all channels) +void USBMidi::sendStop(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_STOP ; + writePacket(outPacket.i); +} + +// Send a Midi ACTIVE SENSE message (ACTIVE SENSE is always for all channels) +void USBMidi::sendActiveSense(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_ACTIVE_SENSE ; + writePacket(outPacket.i); +} + +// Send a Midi RESET message (RESET is always for all channels) +void USBMidi::sendReset(void) +{ + outPacket.p.cable=DEFAULT_MIDI_CABLE; + outPacket.p.cin=CIN_1BYTE; + outPacket.p.midi0=MIDIv1_RESET ; + writePacket(outPacket.i); +} + +const uint32 midiNoteFrequency_10ths[128] = { + 82, 87, 92, 97, 103, 109, 116, 122, 130, 138, 146, 154, 164, 173, 184, 194, + 206, 218, 231, 245, 260, 275, 291, 309, 327, 346, 367, 389, 412, 437, 462, 490, + 519, 550, 583, 617, 654, 693, 734, 778, 824, 873, 925, 980, 1038, 1100, 1165, 1235, + 1308, 1386, 1468, 1556, 1648, 1746, 1850, 1960, 2077, 2200, 2331, 2469, 2616, 2772, 2937, 3111, + 3296, 3492, 3700, 3920, 4153, 4400, 4662, 4939, 5233, 5544, 5873, 6223, 6593, 6985, 7400, 7840, + 8306, 8800, 9323, 9878, 10465, 11087, 11747, 12445, 13185, 13969, 14800, 15680, 16612, 17600, 18647, 19755, + 20930, 22175, 23493, 24890, 26370, 27938, 29600, 31360, 33224, 35200, 37293, 39511, 41860, 44349, 46986, 49780, + 52740, 55877, 59199, 62719, 66449, 70400, 74586, 79021, 83720, 88698, 93973, 99561, 105481, 111753, 118398, 125439 }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +// Placeholders. You should subclass the Midi base class and define these to have your +// version called. +void USBMidi::handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {} +void USBMidi::handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {} +void USBMidi::handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity) {} +void USBMidi::handleControlChange(unsigned int channel, unsigned int controller, unsigned int value) {} +void USBMidi::handleProgramChange(unsigned int channel, unsigned int program) {} +void USBMidi::handleAfterTouch(unsigned int channel, unsigned int velocity) {} +void USBMidi::handlePitchChange(unsigned int pitch) {} +void USBMidi::handleSongPosition(unsigned int position) {} +void USBMidi::handleSongSelect(unsigned int song) {} +void USBMidi::handleTuneRequest(void) {} +void USBMidi::handleSync(void) {} +void USBMidi::handleStart(void) {} +void USBMidi::handleContinue(void) {} +void USBMidi::handleStop(void) {} +void USBMidi::handleActiveSense(void) {} +void USBMidi::handleReset(void) {} +#pragma GCC diagnostic pop diff --git a/STM32F1/libraries/USBComposite/USBMIDI.h b/STM32F1/libraries/USBComposite/USBMIDI.h new file mode 100644 index 0000000..e770047 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBMIDI.h @@ -0,0 +1,186 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2013 Magnus Lundin. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @brief Wirish USB MIDI port (MidiUSB). + */ + +#ifndef _USBMIDI_H_ +#define _USBMIDI_H_ + +//#include +#include +#include +#include "usb_generic.h" + +/* + * This is the Midi class. If you are just sending Midi data, you only need to make an + * instance of the class, passing it your USB port -- in most cases it looks like + * + * USBMidi midi; + * + * then you don't need to do anything else; you can start using it to send Midi messages, + * e.g. + * + * midi.sendNoteOn(1, note, velocity); + * + * If you are using it to receive Midi data, it's a little more complex & you will need + * to subclass the Midi class. + * + * For people not used to C++ this may look confusing, but it's actually pretty easy. + * Note that you only need to write the functions for event types you want to handle. + * They should match the names & prototypes of the functions in the class; look at + * the functions in the Midi class below that have the keyword "virtual" to see which + * ones you can use. + * + * Here's an example of one that takes NOTE ON, NOTE OFF, and CONTROL CHANGE: + * + * class MyMidi : public USBMidi { + * public: + * + * // Need this to compile; it just hands things off to the Midi class. + * MyMidi() : USBMidi(s) {} + * + * void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) + * { + * if (note == 40) {digitalWrite(13, HIGH); } + * } + * + * void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) + * { + * if (note == 40) { digitalWrite(13, LOW); } + * } + * + * void handleControlChange(unsigned int channel, unsigned int controller, + * unsigned int value) + * { + * analogWrite(6, value * 2); + * } + * + * Then you need to make an instance of this class: + * + * MyMidi midi(); + * + * If receiving Midi data, you also need to call the poll function every time through + * loop(); e.g. + * + * void loop() { + * midi.poll(); + * } + * + * This causes the Midi class to read data from the USB port and process it. + */ + +class USBMidi { +private: + bool enabled = false; + + /* Private Receive Parameters */ + + // The channel this Midi instance receives data for (0 means all channels) + int channelIn_; + + /* Internal functions */ + + // Called whenever data is read from the USB port + void dispatchPacket(uint32 packet); + +public: + //static bool init(USBMidi* me); + // This registers this USB composite device component with the USBComposite class instance. + bool registerComponent(); + void setChannel(unsigned channel=0); + unsigned getChannel() { + return channelIn_; + } + + // Call to start the USB port, at given baud. For many applications + // the default parameters are just fine (which will cause messages for all + // MIDI channels to be delivered) + void begin(unsigned int channel = 0); + //void begin(); + void end(); + + uint32 available(void); + + uint32 readPackets(void *buf, uint32 len); + uint32 readPacket(void); + + void writePacket(uint32); +// void write(const char *str); + void writePackets(const void*, uint32); + + uint8 isConnected(); + uint8 pending(); + + // poll() should be called every time through loop() IF dealing with incoming MIDI + // (if you're only SENDING MIDI events from the Arduino, you don't need to call + // poll); it causes data to be read from the USB port and processed. + void poll(); + + // Call these to send MIDI messages of the given types + void sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity); + void sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity); + void sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity); + void sendControlChange(unsigned int channel, unsigned int controller, unsigned int value); + void sendProgramChange(unsigned int channel, unsigned int program); + void sendAfterTouch(unsigned int channel, unsigned int velocity); + void sendPitchChange(unsigned int pitch); + void sendSongPosition(unsigned int position); + void sendSongSelect(unsigned int song); + void sendTuneRequest(void); + void sendSync(void); + void sendStart(void); + void sendContinue(void); + void sendStop(void); + void sendActiveSense(void); + void sendReset(void); + + // Overload these in a subclass to get MIDI messages when they come in + virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity); + virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity); + virtual void handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity); + virtual void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value); + virtual void handleProgramChange(unsigned int channel, unsigned int program); + virtual void handleAfterTouch(unsigned int channel, unsigned int velocity); + virtual void handlePitchChange(unsigned int pitch); + virtual void handleSongPosition(unsigned int position); + virtual void handleSongSelect(unsigned int song); + virtual void handleTuneRequest(void); + virtual void handleSync(void); + virtual void handleStart(void); + virtual void handleContinue(void); + virtual void handleStop(void); + virtual void handleActiveSense(void); + virtual void handleReset(void); +}; + +extern USBMidi USBMIDI; + +extern const uint32 midiNoteFrequency_10ths[128]; + +#endif \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/USBMassStorage.cpp b/STM32F1/libraries/USBComposite/USBMassStorage.cpp new file mode 100644 index 0000000..9c96359 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBMassStorage.cpp @@ -0,0 +1,45 @@ +#include "USBMassStorage.h" +#include "usb_mass.h" +#include "usb_mass_mal.h" +#include "usb_composite_serial.h" +#include + +void USBMassStorageDevice::begin() { + if(!enabled) { + USBComposite.clear(); + registerComponent(); + USBComposite.begin(); + + enabled = true; + } +} + +void USBMassStorageDevice::end() { + USBComposite.end(); +} + +void USBMassStorageDevice::loop() { + usb_mass_loop(); +} + +bool USBMassStorageDevice::registerComponent() { + return USBComposite.add(&usbMassPart, this); +} + +void USBMassStorageDevice::setDrive(uint32 driveNumber, uint32 byteSize, MassStorageReader reader, + MassStorageWriter writer, MassStorageStatuser statuser, MassStorageInitializer initializer) { + if (driveNumber >= USB_MASS_MAX_DRIVES) + return; + usb_mass_drives[driveNumber].blockCount = byteSize/512; + usb_mass_drives[driveNumber].read = reader; + usb_mass_drives[driveNumber].write = writer; + usb_mass_drives[driveNumber].status = statuser; + usb_mass_drives[driveNumber].init = initializer; + usb_mass_drives[driveNumber].format = initializer; +} + +void USBMassStorageDevice::clearDrives() { + memset(usb_mass_drives, 0, sizeof(usb_mass_drives)); +} + +USBMassStorageDevice MassStorage; diff --git a/STM32F1/libraries/USBComposite/USBMassStorage.h b/STM32F1/libraries/USBComposite/USBMassStorage.h new file mode 100644 index 0000000..02663ab --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBMassStorage.h @@ -0,0 +1,25 @@ +#ifndef USBMASSSTORAGE_H +#define USBMASSSTORAGE_H + +#include +#include "USBComposite.h" +#include "usb_generic.h" +#include "usb_mass_mal.h" + +class USBMassStorageDevice { +private: + bool enabled = false; +public: + void begin(); + void end(); + void loop(); + void clearDrives(void); + bool registerComponent(); + void setDrive(uint32 driveNumber, uint32 byteSize, MassStorageReader reader, + MassStorageWriter writer = NULL, MassStorageStatuser = NULL, MassStorageInitializer = NULL); +}; + +extern USBMassStorageDevice MassStorage; + +#endif /* USBMASSSTORAGE_H */ + diff --git a/STM32F1/libraries/USBComposite/USBXBox360.cpp b/STM32F1/libraries/USBComposite/USBXBox360.cpp new file mode 100644 index 0000000..83237c0 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBXBox360.cpp @@ -0,0 +1,173 @@ +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +/** + * @brief USB HID Keyboard device + */ + +#include +#include +#include +#include +#include "USBXBox360.h" +#include "usb_x360.h" + +void USBXBox360::sendReport(void){ + x360_tx(xbox360_Report, sizeof(xbox360_Report)); + + while (x360_is_transmitting() != 0) { + } + /* flush out to avoid having the pc wait for more data */ + x360_tx(NULL, 0); +} + +void USBXBox360::setRumbleCallback(void (*callback)(uint8 left, uint8 right)) { + x360_set_rumble_callback(callback); +} + +void USBXBox360::setLEDCallback(void (*callback)(uint8 pattern)) { + x360_set_led_callback(callback); +} + + +bool USBXBox360::init(void* ignore) { + (void)ignore; + usb_generic_set_info(0x045e, 0x028e, NULL, NULL, NULL); + return true; +} + +bool USBXBox360::registerComponent() { + return USBComposite.add(&usbX360Part, this, init); +} + +void USBXBox360::begin(void){ + if(!enabled){ + USBComposite.clear(); + registerComponent(); + USBComposite.begin(); + + enabled = true; + } +} + +void USBXBox360::end() { + if (enabled) { + enabled = false; + USBComposite.end(); + } +} + +void USBXBox360::stop(void){ + setRumbleCallback(NULL); + setLEDCallback(NULL); +} + +void USBXBox360::setManualReportMode(bool mode) { + manualReport = mode; +} + +bool USBXBox360::getManualReportMode() { + return manualReport; +} + +void USBXBox360::safeSendReport() { + if (!manualReport) { + while (x360_is_transmitting() != 0) { + } + sendReport(); + } +} + +void USBXBox360::send() { + while (x360_is_transmitting() != 0) { + } + sendReport(); +} + +void USBXBox360::button(uint8_t button, bool val){ + button--; + uint8_t mask = (1 << (button & 7)); + if (val) { + if (button < 8) xbox360_Report[2] |= mask; + else if (button < 16) xbox360_Report[3] |= mask; + } else { + mask = ~mask; + if (button < 8) xbox360_Report[2] &= mask; + else if (button < 16) xbox360_Report[3] &= mask; + } + + safeSendReport(); +} + +void USBXBox360::X(int16_t val){ + xbox360_Report[6] = val; + xbox360_Report[7] = (uint16)val >> 8; + + safeSendReport(); +} + +void USBXBox360::Y(int16_t val){ + xbox360_Report[8] = val; + xbox360_Report[9] = (uint16)val >> 8; + + safeSendReport(); +} + +void USBXBox360::XRight(int16_t val){ + xbox360_Report[0xA] = val; + xbox360_Report[0xB] = (uint16)val >> 8; + + safeSendReport(); +} + +void USBXBox360::YRight(int16_t val){ + xbox360_Report[0xC] = val; + xbox360_Report[0xD] = (uint16)val >> 8; + + safeSendReport(); +} + +void USBXBox360::position(int16_t x, int16_t y){ + xbox360_Report[6] = x; + xbox360_Report[7] = (uint16)x >> 8; + xbox360_Report[8] = y; + xbox360_Report[9] = (uint16)y >> 8; + + safeSendReport(); +} + +void USBXBox360::positionRight(int16_t x, int16_t y){ + xbox360_Report[0xA] = x; + xbox360_Report[0xB] = (uint16)x >> 8; + xbox360_Report[0xC] = y; + xbox360_Report[0xD] = (uint16)y >> 8; + + safeSendReport(); +} + +void USBXBox360::sliderLeft(uint8_t val){ + xbox360_Report[4] = val; + + safeSendReport(); +} + +void USBXBox360::sliderRight(uint8_t val){ + xbox360_Report[5] = val; + + safeSendReport(); +} + +USBXBox360 XBox360; diff --git a/STM32F1/libraries/USBComposite/USBXBox360.h b/STM32F1/libraries/USBComposite/USBXBox360.h new file mode 100644 index 0000000..e48e7a7 --- /dev/null +++ b/STM32F1/libraries/USBComposite/USBXBox360.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#ifndef _USBXBox360_H +#define _USBXBox360_H + +#include +#include +#include "USBComposite.h" +#include "usb_generic.h" + +class USBXBox360 { +private: + uint8_t xbox360_Report[20] = {0,0x14};// 3,0,0,0,0,0x0F,0x20,0x80,0x00,0x02,0x08,0x20,0x80}; + bool manualReport = false; + bool enabled; + void safeSendReport(void); + void sendReport(void); +public: + void send(void); + static bool init(void* ignore); + bool registerComponent(); + void stop(); + void setManualReportMode(bool manualReport); + bool getManualReportMode(); + void begin(void); + void end(void); + void button(uint8_t button, bool val); + void X(int16_t val); + void Y(int16_t val); + void position(int16_t x, int16_t y); + void positionRight(int16_t x, int16_t y); + void XRight(int16_t val); + void YRight(int16_t val); + void sliderLeft(uint8_t val); + void sliderRight(uint8_t val); + void hat(int16_t dir); + void setLEDCallback(void (*callback)(uint8 pattern)); + void setRumbleCallback(void (*callback)(uint8 left, uint8 right)); +}; + +extern USBXBox360 XBox360; + +#endif + diff --git a/STM32F1/libraries/USBComposite/examples/BootKeyboard/BootKeyboard.ino b/STM32F1/libraries/USBComposite/examples/BootKeyboard/BootKeyboard.ino new file mode 100644 index 0000000..72b42f5 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/BootKeyboard/BootKeyboard.ino @@ -0,0 +1,15 @@ +#include + +void setup() +{ + USBHID_begin_with_serial(HID_BOOT_KEYBOARD); + BootKeyboard.begin(); // needed just in case you need LED support +} + +void loop() +{ + BootKeyboard.press(KEY_F12); + delay(100); + BootKeyboard.release(KEY_F12); + delay(1000); +} diff --git a/STM32F1/libraries/USBComposite/examples/absmouse/absmouse.ino b/STM32F1/libraries/USBComposite/examples/absmouse/absmouse.ino new file mode 100644 index 0000000..29368ea --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/absmouse/absmouse.ino @@ -0,0 +1,25 @@ +#include + +const uint8_t reportDescription[] = { + HID_ABS_MOUSE_REPORT_DESCRIPTOR(HID_MOUSE_REPORT_ID) +}; + +HIDAbsMouse mouse; + +void setup(){ + USBHID_begin_with_serial(reportDescription, sizeof(reportDescription)); + delay(1000); + mouse.move(0,0); + delay(1000); + mouse.press(MOUSE_LEFT); + mouse.move(500,500); + mouse.release(MOUSE_ALL); + mouse.click(MOUSE_RIGHT); +} + +void loop(){ + mouse.move(0,0); + delay(1000); + mouse.move(16384,16384); + delay(1000); +} diff --git a/STM32F1/libraries/USBComposite/examples/consumer/consumer.ino b/STM32F1/libraries/USBComposite/examples/consumer/consumer.ino new file mode 100644 index 0000000..9cf9c9f --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/consumer/consumer.ino @@ -0,0 +1,18 @@ +#include + +const uint8_t reportDescription[] = { + HID_CONSUMER_REPORT_DESCRIPTOR() +}; + +HIDConsumer Consumer; + +void setup(){ + USBHID_begin_with_serial(reportDescription, sizeof(reportDescription)); +} + +void loop() { + Consumer.press(HIDConsumer::BRIGHTNESS_DOWN); + Consumer.release(); + delay(500); +} + diff --git a/STM32F1/libraries/USBComposite/examples/jigglemouse/jigglemouse.ino b/STM32F1/libraries/USBComposite/examples/jigglemouse/jigglemouse.ino new file mode 100755 index 0000000..633db0c --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/jigglemouse/jigglemouse.ino @@ -0,0 +1,23 @@ +#include + +#define LED PB12 + +void setup(){ + pinMode(LED,OUTPUT); + digitalWrite(LED,1); + USBHID_begin_with_serial(HID_MOUSE); + delay(1000); +} + +void loop(){ + digitalWrite(LED,0); + Mouse.move(4,0); + delay(500); + digitalWrite(LED,1); + delay(30000); + digitalWrite(LED,0); + Mouse.move(-4,0); + delay(500); + digitalWrite(LED,1); + delay(30000); +} diff --git a/STM32F1/libraries/USBComposite/examples/keyboardwithleds/keyboardwithleds.ino b/STM32F1/libraries/USBComposite/examples/keyboardwithleds/keyboardwithleds.ino new file mode 100644 index 0000000..d45a312 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/keyboardwithleds/keyboardwithleds.ino @@ -0,0 +1,14 @@ +#include + + +void setup() { + USBHID_begin_with_serial(HID_KEYBOARD); + Keyboard.begin(); // needed for LED support + delay(1000); +} + +void loop() { + CompositeSerial.println(Keyboard.getLEDs()); +} + + diff --git a/STM32F1/libraries/USBComposite/examples/mass/image.h b/STM32F1/libraries/USBComposite/examples/mass/image.h new file mode 100644 index 0000000..f96b941 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/mass/image.h @@ -0,0 +1,67 @@ +uint8 image[11776] = { +0xEB,0x3C,0x90,0x6D,0x6B,0x64,0x6F,0x73,0x66,0x73,0x00,0x00,0x02,0x04,0x01,0x00, +0x02,0x10,0x00,0x17,0x00,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xDB,0x32,0x73,0x5A,0x20,0x20,0x20,0x20,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0x0E,0x1F, +0xBE,0x5B,0x7C,0xAC,0x22,0xC0,0x74,0x0B,0x56,0xB4,0x0E,0xBB,0x07,0x00,0xCD,0x10, +0x5E,0xEB,0xF0,0x32,0xE4,0xCD,0x16,0xCD,0x19,0xEB,0xFE,0x54,0x68,0x69,0x73,0x20, +0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x61,0x20,0x62,0x6F,0x6F,0x74,0x61,0x62,0x6C, +0x65,0x20,0x64,0x69,0x73,0x6B,0x2E,0x20,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20, +0x69,0x6E,0x73,0x65,0x72,0x74,0x20,0x61,0x20,0x62,0x6F,0x6F,0x74,0x61,0x62,0x6C, +0x65,0x20,0x66,0x6C,0x6F,0x70,0x70,0x79,0x20,0x61,0x6E,0x64,0x0D,0x0A,0x70,0x72, +0x65,0x73,0x73,0x20,0x61,0x6E,0x79,0x20,0x6B,0x65,0x79,0x20,0x74,0x6F,0x20,0x74, +0x72,0x79,0x20,0x61,0x67,0x61,0x69,0x6E,0x20,0x2E,0x2E,0x2E,0x20,0x0D,0x0A,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xAA, +0xF8,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xF8,0xFF,0xFF, +}; diff --git a/STM32F1/libraries/USBComposite/examples/mass/mass.ino b/STM32F1/libraries/USBComposite/examples/mass/mass.ino new file mode 100644 index 0000000..e64e40d --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/mass/mass.ino @@ -0,0 +1,68 @@ +#include + +#define PRODUCT_ID 0x29 + +#include "image.h" + +bool write(uint32_t memoryOffset, const uint8_t *writebuff, uint16_t transferLength) { + memcpy(image+memoryOffset, writebuff, transferLength); + + return true; +} + +bool read(uint32_t memoryOffset, uint8_t *readbuff, uint16_t transferLength) { + memcpy(readbuff, image+memoryOffset, transferLength); + + return true; +} + +char hexNibble(uint8 x) { + return x < 10 ? x + '0' : x + 'A' - 10; +} + +char* format16(uint16 c) { + static char str[6]; + str[5] = 0; + char *p = str+5; + do { + *--p = (c % 10) + '0'; + c /= 10; + } while(c); + return p; +} + +void dumpDrive() { + char hex[7] = "0x11,"; + CompositeSerial.print("uint8 image["); + CompositeSerial.print(format16(sizeof(image))); + CompositeSerial.println("] = {"); + int last; + for (last=sizeof(image)-1;last>=0 && image[last] == 0;last--); + if (last<0) last=0; + + for (int i=0; i<=last; i++) { + if (i && i % 16 == 0) + CompositeSerial.println(""); + hex[2] = hexNibble(image[i]>>4); + hex[3] = hexNibble(image[i]&0xF); + CompositeSerial.print(hex); + } + CompositeSerial.println("\n};\n"); +} + +void setup() { + USBComposite.setProductId(PRODUCT_ID); + MassStorage.setDrive(0, sizeof(image), read, write); + MassStorage.registerComponent(); + CompositeSerial.registerComponent(); + USBComposite.begin(); + delay(2000); +} + +void loop() { + MassStorage.loop(); + if (CompositeSerial.available() && 'd' == CompositeSerial.read()) { + dumpDrive(); + } +} + diff --git a/STM32F1/libraries/USBComposite/examples/midiin/midiin.ino b/STM32F1/libraries/USBComposite/examples/midiin/midiin.ino new file mode 100644 index 0000000..20da70a --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/midiin/midiin.ino @@ -0,0 +1,27 @@ +#include + +#define SPEAKER_PIN PA0 + +class myMidi : public USBMidi { + virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) { + noTone(SPEAKER_PIN); + } + virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) { + tone(SPEAKER_PIN, (midiNoteFrequency_10ths[note]+5)/10); + } + +}; + +myMidi midi; + +void setup() { + pinMode(SPEAKER_PIN, OUTPUT); + midi.registerComponent(); + CompositeSerial.registerComponent(); + USBComposite.begin(); +} + +void loop() { + midi.poll(); +} + diff --git a/STM32F1/libraries/USBComposite/examples/midiout/midiout.ino b/STM32F1/libraries/USBComposite/examples/midiout/midiout.ino new file mode 100644 index 0000000..3fe98b0 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/midiout/midiout.ino @@ -0,0 +1,17 @@ +#include + +const uint8_t notes[] = {60, 62, 64, 65, 67, 69, 71, 72, 61, 63, 66, 68, 70}; +const int numNotes = sizeof(notes)/sizeof(*notes); + +void setup() { + USBMIDI.begin(); + delay(1000); +} + +void loop() { + for (int i=0;i + +#define TXSIZE 256 +#define RXSIZE 300 + +HIDRaw raw; +uint8 buf[RXSIZE]; + +const uint8_t reportDescription[] = { + HID_RAW_REPORT_DESCRIPTOR(TXSIZE,RXSIZE) +}; + +void setup(){ + USBHID_begin_with_serial(reportDescription, sizeof(reportDescription)); + raw.begin(); +} + +void loop() { + if (raw.getOutput(buf)) { + for (int i=0;i +#include +#include "SdFat.h" + +#define LED_PIN PB12 +#define PRODUCT_ID 0x29 + +SdFatEX sd; +const uint32_t speed = SPI_CLOCK_DIV2 ; +const uint8_t SD_CHIP_SELECT = SS; +bool enabled = false; +uint32 cardSize; + +bool write(uint32_t memoryOffset, const uint8_t *writebuff, uint16_t transferLength) { + return sd.card()->writeBlocks(memoryOffset/512, writebuff, transferLength/512); +} + +bool read(uint32_t memoryOffset, uint8_t *readbuff, uint16_t transferLength) { + return sd.card()->readBlocks(memoryOffset/512, readbuff, transferLength/512); +} + +void setup() { + USBComposite.setProductId(PRODUCT_ID); + pinMode(LED_PIN,OUTPUT); + digitalWrite(LED_PIN,1); +} + +void initReader() { + digitalWrite(LED_PIN,0); + cardSize = sd.card()->cardSize(); + MassStorage.setDrive(0, cardSize*512, read, write); + MassStorage.registerComponent(); + CompositeSerial.registerComponent(); + USBComposite.begin(); + enabled=true; +} + +void loop() { + if (!enabled) { + if (sd.begin(SD_CHIP_SELECT)) { + initReader(); + } + else { + delay(50); + } + } + else { + MassStorage.loop(); + } +} + diff --git a/STM32F1/libraries/USBComposite/examples/simplejoystick/simplejoystick.ino b/STM32F1/libraries/USBComposite/examples/simplejoystick/simplejoystick.ino new file mode 100644 index 0000000..f0c75df --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/simplejoystick/simplejoystick.ino @@ -0,0 +1,13 @@ +#include + +void setup() { + USBHID_begin_with_serial(HID_JOYSTICK); +} + +void loop() { + Joystick.X(0); + delay(500); + Joystick.X(1023); + delay(500); +} + diff --git a/STM32F1/libraries/USBComposite/examples/simplekeyboard/simplekeyboard.ino b/STM32F1/libraries/USBComposite/examples/simplekeyboard/simplekeyboard.ino new file mode 100644 index 0000000..80c296f --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/simplekeyboard/simplekeyboard.ino @@ -0,0 +1,13 @@ +#include + +void setup() { + USBHID_begin_with_serial(HID_KEYBOARD); + Keyboard.begin(); // useful to detect host capslock state and LEDs + delay(1000); +} + +void loop() { + Keyboard.println("Hello world"); + delay(10000); +} + diff --git a/STM32F1/libraries/USBComposite/examples/softjoystick/send.py b/STM32F1/libraries/USBComposite/examples/softjoystick/send.py new file mode 100644 index 0000000..5025db9 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/softjoystick/send.py @@ -0,0 +1,60 @@ +from pywinusb import hid +from time import sleep + +REPORT_ID = 20 +HID_REPORT_FEATURE = 3 + +device = hid.HidDeviceFilter(vendor_id = 0x1EAF).get_devices()[0] # , product_id = 0x0024 +print(device) +device.open() + +""" + uint8_t reportID; + uint32_t buttons; + unsigned hat:4; + unsigned x:10; + unsigned y:10; + unsigned rx:10; + unsigned ry:10; + unsigned sliderLeft:10; + unsigned sliderRight:10; +""" + +def toBits(n,bits): + return tuple((n>>i)&1 for i in range(bits)) + +def getByteFromBits(bits,n): + out = 0 + for i in range(8): + out += bits[8*n+i] << i + return out + +def joystickData(reportID=REPORT_ID, buttons=0, hat=15, x=512, y=512, rx=512, ry=512, sliderLeft=512, sliderRight=512): + joyData = ( toBits(reportID,8) + toBits(buttons,32) + toBits(hat,4) + toBits(x,10) + toBits(y,10) + + toBits(rx,10) + toBits(ry,10) + toBits(sliderLeft,10) + toBits(sliderRight,10) ) + out = [getByteFromBits(joyData,n) for n in range(13)] + print(out) + return out + +myReport = None + +for report in device.find_feature_reports(): + if report.report_id == REPORT_ID and report.report_type == "Feature": + myReport = report + break +if myReport is None: + for report in device.find_output_reports(): + if report.report_id == REPORT_ID and report.report_type == "Output": + myReport = report + break + +assert myReport is not None + +while True: + myReport.set_raw_data(joystickData(buttons=7,x=0,y=0)) + + myReport.send() + sleep(0.5) + myReport.set_raw_data(joystickData(buttons=0,x=1023,y=1023)) + myReport.send() + sleep(0.5) diff --git a/STM32F1/libraries/USBComposite/examples/softjoystick/softjoystick.ino b/STM32F1/libraries/USBComposite/examples/softjoystick/softjoystick.ino new file mode 100644 index 0000000..0fe9b55 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/softjoystick/softjoystick.ino @@ -0,0 +1,47 @@ +// This is a silly project: you send a feature +// report from the PC, and it becomes a joystick setting. +// I guess it's not completely useless as it lets you +// get vJoy functionality without special vJoy drivers. + +#include + +#define DATA_SIZE (sizeof(JoystickReport_t)-1) + +class HIDJoystickRawData : public HIDJoystick { + private: + uint8_t featureData[HID_BUFFER_ALLOCATE_SIZE(DATA_SIZE,1)]; + HIDBuffer_t fb { featureData, HID_BUFFER_SIZE(DATA_SIZE,1), HID_JOYSTICK_REPORT_ID }; + public: + HIDJoystickRawData(uint8_t reportID=HID_JOYSTICK_REPORT_ID) : HIDJoystick(reportID) {} + + void begin() { + USBHID.setFeatureBuffers(&fb, 1); + } + + void setRawData(JoystickReport_t* p) { + joyReport = *p; + send(); + } +}; + +HIDJoystickRawData joy; +JoystickReport_t report = {HID_JOYSTICK_REPORT_ID}; + +const uint8_t reportDescription[] = { + HID_JOYSTICK_REPORT_DESCRIPTOR(HID_JOYSTICK_REPORT_ID, + HID_FEATURE_REPORT_DESCRIPTOR(DATA_SIZE)) +}; + +void setup() { + USBHID_begin_with_serial(reportDescription, sizeof(reportDescription)); + joy.begin(); +} + +void loop() { + if (joy.getFeature(1+(uint8_t*)&report)) { + joy.setRawData(&report); + } + + delay(5); +} + diff --git a/STM32F1/libraries/USBComposite/examples/twojoysticks/twojoysticks.ino b/STM32F1/libraries/USBComposite/examples/twojoysticks/twojoysticks.ino new file mode 100644 index 0000000..7cf929d --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/twojoysticks/twojoysticks.ino @@ -0,0 +1,40 @@ +#include + +const uint8_t reportDescription[] = { + HID_MOUSE_REPORT_DESCRIPTOR(), + HID_KEYBOARD_REPORT_DESCRIPTOR(), + HID_JOYSTICK_REPORT_DESCRIPTOR(), + HID_JOYSTICK_REPORT_DESCRIPTOR(HID_JOYSTICK_REPORT_ID+1), +}; + +HIDJoystick Joystick2(HID_JOYSTICK_REPORT_ID+1); + +void setup(){ + USBHID_begin_with_serial(reportDescription, sizeof(reportDescription)); + Joystick.setManualReportMode(true); + Joystick2.setManualReportMode(true); +} + +void loop(){ + Joystick.X(0); + Joystick.Y(0); + Joystick.sliderRight(1023); + Joystick.send(); + delay(400); + Joystick.X(1023); + Joystick.Y(1023); + Joystick.sliderRight(0); + Joystick.send(); + delay(400); + Joystick2.X(0); + Joystick2.Y(0); + Joystick2.sliderRight(1023); + Joystick2.send(); + delay(400); + Joystick2.X(1023); + Joystick2.Y(1023); + Joystick2.sliderRight(0); + Joystick2.send(); + delay(400); +} + diff --git a/STM32F1/libraries/USBComposite/examples/x360/x360.ino b/STM32F1/libraries/USBComposite/examples/x360/x360.ino new file mode 100644 index 0000000..d97a7f3 --- /dev/null +++ b/STM32F1/libraries/USBComposite/examples/x360/x360.ino @@ -0,0 +1,15 @@ +#include + +void setup() { + XBox360.begin(); + delay(1000); +} + +void loop() { + XBox360.X(-32767); + XBox360.Y(-32767); + delay(1000); + XBox360.X(32767); + XBox360.Y(32767); + delay(1000); +} diff --git a/STM32F1/libraries/USBComposite/keywords.txt b/STM32F1/libraries/USBComposite/keywords.txt new file mode 100644 index 0000000..3092c00 --- /dev/null +++ b/STM32F1/libraries/USBComposite/keywords.txt @@ -0,0 +1,89 @@ +####################################### +# Syntax Coloring Map USBHID +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +HID KEYWORD1 +Joystick KEYWORD1 +Keyboard KEYWORD1 +Mouse KEYWORD1 +CompositeSerial KEYWORD1 +XBox360 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 +XRight KEYWORD2 +YRight KEYWORD2 +Yrotate KEYWORD2 +Y KEYWORD2 +Xrotate KEYWORD2 +X KEYWORD2 +sliderLeft KEYWORD2 +sliderRight KEYWORD2 +button KEYWORD2 +hat KEYWORD2 +setManualReportMode KEYWORD2 +getManualReportMode KEYWORD2 +release KEYWORD2 +press KEYWORD2 +releaseAll KEYWORD2 +move KEYWORD2 +send KEYWORD2 +click KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +USB_HID_MOUSE LITERAL1 +USB_HID_KEYBOARD LITERAL1 +USB_HID_JOYSTICK LITERAL1 +USB_HID_KEYBOARD_MOUSE LITERAL1 +USB_HID_KEYBOARD_MOUSE_JOYSTICK LITERAL1 +USB_HID_KEYBOARD_JOYSTICK LITERAL1 +KEY_LEFT_CTRL LITERAL1 +KEY_LEFT_SHIFT LITERAL1 +KEY_LEFT_ALT LITERAL1 +KEY_LEFT_GUI LITERAL1 +KEY_RIGHT_CTRL LITERAL1 +KEY_RIGHT_SHIFT LITERAL1 +KEY_RIGHT_ALT LITERAL1 +KEY_RIGHT_GUI LITERAL1 +KEY_UP_ARROW LITERAL1 +KEY_DOWN_ARROW LITERAL1 +KEY_LEFT_ARROW LITERAL1 +KEY_RIGHT_ARROW LITERAL1 +KEY_BACKSPACE LITERAL1 +KEY_TAB LITERAL1 +KEY_RETURN LITERAL1 +KEY_ESC LITERAL1 +KEY_INSERT LITERAL1 +KEY_DELETE LITERAL1 +KEY_PAGE_UP LITERAL1 +KEY_PAGE_DOWN LITERAL1 +KEY_HOME LITERAL1 +KEY_END LITERAL1 +KEY_CAPS_LOCK LITERAL1 +KEY_F1 LITERAL1 +KEY_F2 LITERAL1 +KEY_F3 LITERAL1 +KEY_F4 LITERAL1 +KEY_F5 LITERAL1 +KEY_F6 LITERAL1 +KEY_F7 LITERAL1 +KEY_F8 LITERAL1 +KEY_F9 LITERAL1 +KEY_F10 LITERAL1 +KEY_F11 LITERAL1 +KEY_F12 LITERAL1 +MOUSE_LEFT LITERAL1 +MOUSE_MIDDLE LITERAL1 +MOUSE_RIGHT LITERAL1 +MOUSE_ALL LITERAL1 +HIDConsumer LITERAL1 diff --git a/STM32F1/libraries/USBComposite/library.properties b/STM32F1/libraries/USBComposite/library.properties new file mode 100644 index 0000000..3fd8bca --- /dev/null +++ b/STM32F1/libraries/USBComposite/library.properties @@ -0,0 +1,10 @@ +name=USBComposite for STM32F1 +version=0.66 +author=Various +email=arpruss@gmail.com +sentence=USB HID / MIDI / mass storage library for STM32F1 +paragraph=USB HID / MIDI / mass storage library for STM32F1 +url=https://github.com/arpruss/USBHID_stm32f1 +architectures=STM32F1 +maintainer=arpruss@gmail.com +category=Communication \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/usb_composite_serial.c b/STM32F1/libraries/USBComposite/usb_composite_serial.c new file mode 100644 index 0000000..51fc3ac --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_composite_serial.c @@ -0,0 +1,580 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usb/stm32f1/usb_hid.c + * @brief USB HID (human interface device) support + * + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include "usb_composite_serial.h" +#include "usb_generic.h" +#include +#include +#include +#include + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" + +#define CDCACM_ENDPOINT_TX 0 +#define CDCACM_ENDPOINT_MANAGEMENT 1 +#define CDCACM_ENDPOINT_RX 2 + +uint16 GetEPTxAddr(uint8 /*bEpNum*/); + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +static void serialUSBReset(void); +static RESULT serialUSBDataSetup(uint8 request); +static RESULT serialUSBNoDataSetup(uint8 request); +static void vcomDataTxCb(void); +static void vcomDataRxCb(void); + +#define NUM_SERIAL_ENDPOINTS 3 +#define CCI_INTERFACE_OFFSET 0x00 +#define DCI_INTERFACE_OFFSET 0x01 +#define SERIAL_MANAGEMENT_INTERFACE_NUMBER (CCI_INTERFACE_OFFSET+usbSerialPart.startInterface) + +/* + * Descriptors + */ + + +typedef struct { + //CDCACM + IADescriptor IAD; + usb_descriptor_interface CCI_Interface; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement; + CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union; + usb_descriptor_endpoint ManagementEndpoint; + usb_descriptor_interface DCI_Interface; + usb_descriptor_endpoint DataOutEndpoint; + usb_descriptor_endpoint DataInEndpoint; +} __packed serial_part_config; + + +static const serial_part_config serialPartConfigData = { + .IAD = { + .bLength = 0x08, + .bDescriptorType = 0x0B, + .bFirstInterface = CCI_INTERFACE_OFFSET, // PATCH + .bInterfaceCount = 0x02, + .bFunctionClass = 0x02, + .bFunctionSubClass = 0x02, + .bFunctionProtocol = 0x01, + .iFunction = 0x02, + }, + .CCI_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = CCI_INTERFACE_OFFSET, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x01, + .bInterfaceClass = USB_INTERFACE_CLASS_CDC, + .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM, + .bInterfaceProtocol = 0x01, /* Common AT Commands */ + .iInterface = 0x00, + }, + + .CDC_Functional_IntHeader = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x00, + .Data = {0x01, 0x10}, + }, + + .CDC_Functional_CallManagement = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x01, + .Data = {0x03, DCI_INTERFACE_OFFSET}, // PATCH + }, + + .CDC_Functional_ACM = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1), + .bDescriptorType = 0x24, + .SubType = 0x02, + .Data = {0x06}, + }, + + .CDC_Functional_Union = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x06, + .Data = {CCI_INTERFACE_OFFSET, DCI_INTERFACE_OFFSET}, // PATCH, PATCH + }, + + .ManagementEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | + CDCACM_ENDPOINT_MANAGEMENT), // PATCH + .bmAttributes = USB_EP_TYPE_INTERRUPT, + .wMaxPacketSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, + .bInterval = 0xFF, + }, + + .DCI_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = DCI_INTERFACE_OFFSET, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = USB_INTERFACE_CLASS_DIC, + .bInterfaceSubClass = 0x00, /* None */ + .bInterfaceProtocol = 0x00, /* None */ + .iInterface = 0x00, + }, + + .DataOutEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | + CDCACM_ENDPOINT_RX), // patch + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USBHID_CDCACM_RX_EPSIZE, + .bInterval = 0x00, + }, + + .DataInEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | CDCACM_ENDPOINT_TX), // PATCH + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USBHID_CDCACM_TX_EPSIZE, + .bInterval = 0x00, + } +}; + +#define OUT_BYTE(s,v) out[(uint8*)&(s.v)-(uint8*)&s] + +static USBEndpointInfo serialEndpoints[3] = { + { + .callback = vcomDataTxCb, + .bufferSize = USBHID_CDCACM_TX_EPSIZE, + .type = USB_EP_EP_TYPE_BULK, + .tx = 1, + }, + { + .callback = NULL, + .bufferSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, + .type = USB_EP_EP_TYPE_INTERRUPT, + .tx = 1, + }, + { + .callback = vcomDataRxCb, + .bufferSize = USBHID_CDCACM_RX_EPSIZE, + .type = USB_EP_EP_TYPE_BULK, + .tx = 0, + }, +}; + +static void getSerialPartDescriptor(uint8* out) { + memcpy(out, &serialPartConfigData, sizeof(serial_part_config)); + + // patch to reflect where the part goes in the descriptor + OUT_BYTE(serialPartConfigData, ManagementEndpoint.bEndpointAddress) += usbSerialPart.startEndpoint; + OUT_BYTE(serialPartConfigData, DataOutEndpoint.bEndpointAddress) += usbSerialPart.startEndpoint; + OUT_BYTE(serialPartConfigData, DataInEndpoint.bEndpointAddress) += usbSerialPart.startEndpoint; + + OUT_BYTE(serialPartConfigData, IAD.bFirstInterface) += usbSerialPart.startInterface; + OUT_BYTE(serialPartConfigData, CCI_Interface.bInterfaceNumber) += usbSerialPart.startInterface; + OUT_BYTE(serialPartConfigData, DCI_Interface.bInterfaceNumber) += usbSerialPart.startInterface; + OUT_BYTE(serialPartConfigData, CDC_Functional_CallManagement.Data[1]) += usbSerialPart.startInterface; + OUT_BYTE(serialPartConfigData, CDC_Functional_Union.Data[0]) += usbSerialPart.startInterface; + OUT_BYTE(serialPartConfigData, CDC_Functional_Union.Data[1]) += usbSerialPart.startInterface; +} + +USBCompositePart usbSerialPart = { + .numInterfaces = 2, + .numEndpoints = sizeof(serialEndpoints)/sizeof(*serialEndpoints), + .descriptorSize = sizeof(serial_part_config), + .getPartDescriptor = getSerialPartDescriptor, + .usbInit = NULL, + .usbReset = serialUSBReset, + .usbDataSetup = serialUSBDataSetup, + .usbNoDataSetup = serialUSBNoDataSetup, + .endpoints = serialEndpoints +}; + +#define CDC_SERIAL_RX_BUFFER_SIZE 256 // must be power of 2 +#define CDC_SERIAL_RX_BUFFER_SIZE_MASK (CDC_SERIAL_RX_BUFFER_SIZE-1) + +/* Received data */ +static volatile uint8 vcomBufferRx[CDC_SERIAL_RX_BUFFER_SIZE]; +/* Write index to vcomBufferRx */ +static volatile uint32 vcom_rx_head; +/* Read index from vcomBufferRx */ +static volatile uint32 vcom_rx_tail; + +#define CDC_SERIAL_TX_BUFFER_SIZE 256 // must be power of 2 +#define CDC_SERIAL_TX_BUFFER_SIZE_MASK (CDC_SERIAL_TX_BUFFER_SIZE-1) +// Tx data +static volatile uint8 vcomBufferTx[CDC_SERIAL_TX_BUFFER_SIZE]; +// Write index to vcomBufferTx +static volatile uint32 vcom_tx_head; +// Read index from vcomBufferTx +static volatile uint32 vcom_tx_tail; + + + +/* Other state (line coding, DTR/RTS) */ + +static volatile composite_cdcacm_line_coding line_coding = { + /* This default is 115200 baud, 8N1. */ + .dwDTERate = 115200, + .bCharFormat = USBHID_CDCACM_STOP_BITS_1, + .bParityType = USBHID_CDCACM_PARITY_NONE, + .bDataBits = 8, +}; + +/* DTR in bit 0, RTS in bit 1. */ +static volatile uint8 line_dtr_rts = 0; + + +static void (*rx_hook)(unsigned, void*) = 0; +static void (*iface_setup_hook)(unsigned, void*) = 0; + +void composite_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)) { + if (hook_flags & USBHID_CDCACM_HOOK_RX) { + rx_hook = hook; + } + if (hook_flags & USBHID_CDCACM_HOOK_IFACE_SETUP) { + iface_setup_hook = hook; + } +} + +void composite_cdcacm_putc(char ch) { + while (!composite_cdcacm_tx((uint8*)&ch, 1)) + ; +} + +/* This function is non-blocking. + * + * It copies data from a user buffer into the USB peripheral TX + * buffer, and returns the number of bytes copied. */ +uint32 composite_cdcacm_tx(const uint8* buf, uint32 len) +{ + if (len==0) return 0; // no data to send + + uint32 head = vcom_tx_head; // load volatile variable + uint32 tx_unsent = (head - vcom_tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; + + // We can only put bytes in the buffer if there is place + if (len > (CDC_SERIAL_TX_BUFFER_SIZE-tx_unsent-1) ) { + len = (CDC_SERIAL_TX_BUFFER_SIZE-tx_unsent-1); + } + if (len==0) return 0; // buffer full + + uint16 i; + // copy data from user buffer to USB Tx buffer + for (i=0; i= 0); + + if (usbGenericTransmitting<0) { + vcomDataTxCb(); // initiate data transmission + } + + return len; +} + + + +uint32 composite_cdcacm_data_available(void) { + return (vcom_rx_head - vcom_rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; +} + +uint16 composite_cdcacm_get_pending(void) { + return (vcom_tx_head - vcom_tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; +} + +/* Non-blocking byte receive. + * + * Copies up to len bytes from our private data buffer (*NOT* the PMA) + * into buf and deq's the FIFO. */ +uint32 composite_cdcacm_rx(uint8* buf, uint32 len) +{ + /* Copy bytes to buffer. */ + uint32 n_copied = composite_cdcacm_peek(buf, len); + + /* Mark bytes as read. */ + uint16 tail = vcom_rx_tail; // load volatile variable + tail = (tail + n_copied) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + vcom_rx_tail = tail; // store volatile variable + + uint32 rx_unread = (vcom_rx_head - tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + // If buffer was emptied to a pre-set value, re-enable the RX endpoint + if ( rx_unread <= 64 ) { // experimental value, gives the best performance + usb_set_ep_rx_stat(usbSerialPart.endpoints[CDCACM_ENDPOINT_RX].address, USB_EP_STAT_RX_VALID); + } + return n_copied; +} + +/* Non-blocking byte lookahead. + * + * Looks at unread bytes without marking them as read. */ +uint32 composite_cdcacm_peek(uint8* buf, uint32 len) +{ + unsigned i; + uint32 tail = vcom_rx_tail; + uint32 rx_unread = (vcom_rx_head-tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + + if (len > rx_unread) { + len = rx_unread; + } + + for (i = 0; i < len; i++) { + buf[i] = vcomBufferRx[tail]; + tail = (tail + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + } + + return len; +} + +uint32 composite_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len) +{ + unsigned i; + uint32 tail = (vcom_rx_tail + offset) & CDC_SERIAL_RX_BUFFER_SIZE_MASK ; + uint32 rx_unread = (vcom_rx_head-tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + + if (len + offset > rx_unread) { + len = rx_unread - offset; + } + + for (i = 0; i < len; i++) { + buf[i] = vcomBufferRx[tail]; + tail = (tail + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + } + + return len; +} + +/* Roger Clark. Added. for Arduino 1.0 API support of Serial.peek() */ +int composite_cdcacm_peek_char() +{ + if (composite_cdcacm_data_available() == 0) + { + return -1; + } + + return vcomBufferRx[vcom_rx_tail]; +} + +uint8 composite_cdcacm_get_dtr() { + return ((line_dtr_rts & USBHID_CDCACM_CONTROL_LINE_DTR) != 0); +} + +uint8 composite_cdcacm_get_rts() { + return ((line_dtr_rts & USBHID_CDCACM_CONTROL_LINE_RTS) != 0); +} + +void composite_cdcacm_get_line_coding(composite_cdcacm_line_coding *ret) { + ret->dwDTERate = line_coding.dwDTERate; + ret->bCharFormat = line_coding.bCharFormat; + ret->bParityType = line_coding.bParityType; + ret->bDataBits = line_coding.bDataBits; +} + +int composite_cdcacm_get_baud(void) { + return line_coding.dwDTERate; +} + +int composite_cdcacm_get_stop_bits(void) { + return line_coding.bCharFormat; +} + +int composite_cdcacm_get_parity(void) { + return line_coding.bParityType; +} + +int composite_cdcacm_get_n_data_bits(void) { + return line_coding.bDataBits; +} + +/* + * Callbacks + */ +static void vcomDataTxCb(void) +{ + uint32 tail = vcom_tx_tail; // load volatile variable + uint32 tx_unsent = (vcom_tx_head - tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; + if (tx_unsent==0) { + if ( (--usbGenericTransmitting)==0) goto flush_vcom; // no more data to send + return; // it was already flushed, keep Tx endpoint disabled + } + usbGenericTransmitting = 1; + // We can only send up to USBHID_CDCACM_TX_EPSIZE bytes in the endpoint. + if (tx_unsent > USBHID_CDCACM_TX_EPSIZE) { + tx_unsent = USBHID_CDCACM_TX_EPSIZE; + } + // copy the bytes from USB Tx buffer to PMA buffer + uint32 *dst = usb_pma_ptr(usbSerialPart.endpoints[CDCACM_ENDPOINT_TX].pmaAddress); + uint16 tmp = 0; + uint16 val; + unsigned i; + for (i = 0; i < tx_unsent; i++) { + val = vcomBufferTx[tail]; + tail = (tail + 1) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; + if (i&1) { + *dst++ = tmp | (val<<8); + } else { + tmp = val; + } + } + if ( tx_unsent&1 ) { + *dst = tmp; + } + vcom_tx_tail = tail; // store volatile variable +flush_vcom: + // enable Tx endpoint + usb_set_ep_tx_count(usbSerialPart.endpoints[CDCACM_ENDPOINT_TX].address, tx_unsent); + usb_set_ep_tx_stat(usbSerialPart.endpoints[CDCACM_ENDPOINT_TX].address, USB_EP_STAT_TX_VALID); +} + + +static void vcomDataRxCb(void) +{ + uint32 head = vcom_rx_head; // load volatile variable + + uint32 ep_rx_size = usb_get_ep_rx_count(usbSerialPart.endpoints[CDCACM_ENDPOINT_RX].address); + // This copy won't overwrite unread bytes as long as there is + // enough room in the USB Rx buffer for next packet + uint32 *src = usb_pma_ptr(usbSerialPart.endpoints[CDCACM_ENDPOINT_RX].pmaAddress); + uint16 tmp = 0; + uint8 val; + uint32 i; + for (i = 0; i < ep_rx_size; i++) { + if (i&1) { + val = tmp>>8; + } else { + tmp = *src++; + val = tmp&0xFF; + } + vcomBufferRx[head] = val; + head = (head + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + } + vcom_rx_head = head; // store volatile variable + + uint32 rx_unread = (head - vcom_rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + // only enable further Rx if there is enough room to receive one more packet + if ( rx_unread < (CDC_SERIAL_RX_BUFFER_SIZE-USBHID_CDCACM_RX_EPSIZE) ) { + usb_set_ep_rx_stat(usbSerialPart.endpoints[CDCACM_ENDPOINT_RX].address, USB_EP_STAT_RX_VALID); + } + + if (rx_hook) { + rx_hook(USBHID_CDCACM_HOOK_RX, 0); + } +} + +static uint8* vcomGetSetLineCoding(uint16 length) { + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = sizeof(struct composite_cdcacm_line_coding); + } + return (uint8*)&line_coding; +} + +static void serialUSBReset(void) { + //VCOM + vcom_rx_head = 0; + vcom_rx_tail = 0; + vcom_tx_head = 0; + vcom_tx_tail = 0; +} + +static RESULT serialUSBDataSetup(uint8 request) { + uint8* (*CopyRoutine)(uint16) = 0; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT) && + pInformation->USBwIndex0 == SERIAL_MANAGEMENT_INTERFACE_NUMBER) { + switch (request) { + case USBHID_CDCACM_GET_LINE_CODING: + CopyRoutine = vcomGetSetLineCoding; + break; + case USBHID_CDCACM_SET_LINE_CODING: + CopyRoutine = vcomGetSetLineCoding; + break; + default: + break; + } + /* Call the user hook. */ + if (iface_setup_hook) { + uint8 req_copy = request; + iface_setup_hook(USBHID_CDCACM_HOOK_IFACE_SETUP, &req_copy); + } + } + + if (CopyRoutine == NULL){ + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +} + +static RESULT serialUSBNoDataSetup(uint8 request) { + RESULT ret = USB_UNSUPPORT; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT) && + pInformation->USBwIndex0 == SERIAL_MANAGEMENT_INTERFACE_NUMBER) { + switch(request) { + case USBHID_CDCACM_SET_COMM_FEATURE: + /* We support set comm. feature, but don't handle it. */ + ret = USB_SUCCESS; + break; + case USBHID_CDCACM_SET_CONTROL_LINE_STATE: + /* Track changes to DTR and RTS. */ + line_dtr_rts = (pInformation->USBwValues.bw.bb0 & + (USBHID_CDCACM_CONTROL_LINE_DTR | + USBHID_CDCACM_CONTROL_LINE_RTS)); + ret = USB_SUCCESS; + break; + } + /* Call the user hook. */ + if (iface_setup_hook) { + uint8 req_copy = request; + iface_setup_hook(USBHID_CDCACM_HOOK_IFACE_SETUP, &req_copy); + } + } + return ret; +} + diff --git a/STM32F1/libraries/USBComposite/usb_composite_serial.h b/STM32F1/libraries/USBComposite/usb_composite_serial.h new file mode 100644 index 0000000..926901b --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_composite_serial.h @@ -0,0 +1,157 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/usb_device.h + * @brief USB Composite with CDC ACM and HID support + * + * IMPORTANT: this API is unstable, and may change without notice. + */ + +#ifndef _USB_SERIAL_H_ +#define _USB_SERIAL_H_ + +#include +#include +#include "usb_generic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern USBCompositePart usbSerialPart; + +/* + * CDC ACM Requests + */ + +#define USBHID_CDCACM_SET_LINE_CODING 0x20 +#define USBHID_CDCACM_GET_LINE_CODING 0x21 +#define USBHID_CDCACM_SET_COMM_FEATURE 0x02 +#define USBHID_CDCACM_SET_CONTROL_LINE_STATE 0x22 +#define USBHID_CDCACM_CONTROL_LINE_DTR (0x01) +#define USBHID_CDCACM_CONTROL_LINE_RTS (0x02) + +#define USBHID_CDCACM_MANAGEMENT_EPSIZE 0x10 +#define USBHID_CDCACM_RX_EPSIZE 0x40 +#define USBHID_CDCACM_TX_EPSIZE 0x40 +/* + * Descriptors, etc. + */ + + + +#define USBHID_CDCACM_CTRL_ENDP 0 + +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +} IADescriptor; + +#define CDC_FUNCTIONAL_DESCRIPTOR_SIZE(DataSize) (3 + DataSize) +#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint8 SubType; \ + uint8 Data[DataSize]; \ + } __packed + +#define USB_DEVICE_CLASS_CDC 0x02 +#define USB_DEVICE_SUBCLASS_CDC 0x00 +#define USB_INTERFACE_CLASS_CDC 0x02 +#define USB_INTERFACE_SUBCLASS_CDC_ACM 0x02 +#define USB_INTERFACE_CLASS_DIC 0x0A + +/* + * CDC ACM interface + */ + +void composite_cdcacm_putc(char ch); +uint32 composite_cdcacm_tx(const uint8* buf, uint32 len); +uint32 composite_cdcacm_rx(uint8* buf, uint32 len); +uint32 composite_cdcacm_peek(uint8* buf, uint32 len); +uint32 composite_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len); + +uint32 composite_cdcacm_data_available(void); /* in RX buffer */ +uint16 composite_cdcacm_get_pending(void); +uint8 usb_is_transmitting(void); + +uint8 composite_cdcacm_get_dtr(void); +uint8 composite_cdcacm_get_rts(void); + +typedef struct composite_cdcacm_line_coding { + uint32 dwDTERate; /* Baud rate */ + +#define USBHID_CDCACM_STOP_BITS_1 0 +#define USBHID_CDCACM_STOP_BITS_1_5 1 +#define USBHID_CDCACM_STOP_BITS_2 2 + uint8 bCharFormat; /* Stop bits */ + +#define USBHID_CDCACM_PARITY_NONE 0 +#define USBHID_CDCACM_PARITY_ODD 1 +#define USBHID_CDCACM_PARITY_EVEN 2 +#define USBHID_CDCACM_PARITY_MARK 3 +#define USBHID_CDCACM_PARITY_SPACE 4 + uint8 bParityType; /* Parity type */ + + uint8 bDataBits; /* Data bits: 5, 6, 7, 8, or 16 */ +} __packed composite_cdcacm_line_coding; + +/* Retrieve a copy of the current line coding structure. */ +void composite_cdcacm_get_line_coding(composite_cdcacm_line_coding*); + +/* Line coding conveniences. */ +int composite_cdcacm_get_baud(void); /* dwDTERate */ +int composite_cdcacm_get_stop_bits(void); /* bCharFormat */ +int composite_cdcacm_get_parity(void); /* bParityType */ +int composite_cdcacm_get_n_data_bits(void); /* bDataBits */ + +/* + * Hack: hooks for bootloader reset signalling + */ + +#define USBHID_CDCACM_HOOK_RX 0x1 +#define USBHID_CDCACM_HOOK_IFACE_SETUP 0x2 + +void composite_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)); + +static inline __always_inline void composite_cdcacm_remove_hooks(unsigned hook_flags) { + composite_cdcacm_set_hooks(hook_flags, 0); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_generic.c b/STM32F1/libraries/USBComposite/usb_generic.c new file mode 100644 index 0000000..c9ed0b3 --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_generic.c @@ -0,0 +1,531 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usb/stm32f1/usb_hid.c + * @brief USB HID (human interface device) support + * + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include + + +//uint16 GetEPTxAddr(uint8 /*bEpNum*/); + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +#include "usb_generic.h" + +// Are we currently sending an IN packet? +volatile int8 usbGenericTransmitting = -1; + +static uint8* usbGetConfigDescriptor(uint16 length); +static void usbInit(void); +static void usbReset(void); +static void usbClearFeature(void); +static void usbSetConfiguration(void); +static RESULT usbDataSetup(uint8 request); +static RESULT usbNoDataSetup(uint8 request); +static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); +static uint8* usbGetStringDescriptor(uint16 length); +static uint8* usbGetConfigDescriptor(uint16 length); +static uint8* usbGetDeviceDescriptor(uint16 length); +static void usbSetConfiguration(void); +static void usbSetDeviceAddress(void); + +#define LEAFLABS_ID_VENDOR 0x1EAF +#define MAPLE_ID_PRODUCT 0x0004 // was 0x0024 +#define USB_DEVICE_CLASS 0x00 +#define USB_DEVICE_SUBCLASS 0x00 +#define DEVICE_PROTOCOL 0x01 +#define HID_DESCRIPTOR_TYPE 0x21 + +static usb_descriptor_device usbGenericDescriptor_Device = + { + .bLength = sizeof(usb_descriptor_device), + .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = USB_DEVICE_CLASS, + .bDeviceSubClass = USB_DEVICE_SUBCLASS, + .bDeviceProtocol = DEVICE_PROTOCOL, + .bMaxPacketSize0 = 0x40, + .idVendor = LEAFLABS_ID_VENDOR, + .idProduct = MAPLE_ID_PRODUCT, + .bcdDevice = 0x0200, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x00, + .bNumConfigurations = 0x01, +}; + +typedef struct { + usb_descriptor_config_header Config_Header; + uint8 descriptorData[MAX_USB_DESCRIPTOR_DATA_SIZE]; +} __packed usb_descriptor_config; + +static usb_descriptor_config usbConfig; + +#define MAX_POWER (100 >> 1) + +static const usb_descriptor_config_header Base_Header = { + .bLength = sizeof(usb_descriptor_config_header), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 0, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED), + .bMaxPower = MAX_POWER, +}; + +static ONE_DESCRIPTOR Device_Descriptor = { + (uint8*)&usbGenericDescriptor_Device, + sizeof(usb_descriptor_device) +}; + +static ONE_DESCRIPTOR Config_Descriptor = { + (uint8*)&usbConfig, + 0 +}; + +static DEVICE my_Device_Table = { + .Total_Endpoint = 0, + .Total_Configuration = 1 +}; + +/* Unicode language identifier: 0x0409 is US English */ +/* FIXME move to Wirish */ +static const usb_descriptor_string usbHIDDescriptor_LangID = { + .bLength = USB_DESCRIPTOR_STRING_LEN(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {0x09, 0x04}, +}; + +#define default_iManufacturer_length 8 +const usb_descriptor_string usb_generic_default_iManufacturer = { + .bLength = USB_DESCRIPTOR_STRING_LEN(default_iManufacturer_length), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0, 'L', 0, 'a', 0, 'b', 0, 's', 0}, +}; + +#define default_iProduct_length 5 +const usb_descriptor_string usb_generic_default_iProduct = { + .bLength = USB_DESCRIPTOR_STRING_LEN(default_iProduct_length), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0}, +}; + + +#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ +static DEVICE_PROP my_Device_Property = { + .Init = usbInit, + .Reset = usbReset, + .Process_Status_IN = NOP_Process, + .Process_Status_OUT = NOP_Process, + .Class_Data_Setup = usbDataSetup, + .Class_NoData_Setup = usbNoDataSetup, + .Class_Get_Interface_Setting = usbGetInterfaceSetting, + .GetDeviceDescriptor = usbGetDeviceDescriptor, + .GetConfigDescriptor = usbGetConfigDescriptor, + .GetStringDescriptor = usbGetStringDescriptor, + .RxEP_buffer = NULL, + .MaxPacketSize = MAX_PACKET_SIZE +}; + +static const USER_STANDARD_REQUESTS my_User_Standard_Requests = { + .User_GetConfiguration = NOP_Process, + .User_SetConfiguration = usbSetConfiguration, + .User_GetInterface = NOP_Process, + .User_SetInterface = NOP_Process, + .User_GetStatus = NOP_Process, + .User_ClearFeature = usbClearFeature, + .User_SetEndPointFeature = NOP_Process, + .User_SetDeviceFeature = NOP_Process, + .User_SetDeviceAddress = usbSetDeviceAddress +}; + +static uint8 numStringDescriptors = 3; + + +#define MAX_STRING_DESCRIPTORS 4 +static ONE_DESCRIPTOR String_Descriptor[MAX_STRING_DESCRIPTORS] = { + {(uint8*)&usbHIDDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, + {(uint8*)&usb_generic_default_iManufacturer, USB_DESCRIPTOR_STRING_LEN(default_iManufacturer_length)}, + {(uint8*)&usb_generic_default_iProduct, USB_DESCRIPTOR_STRING_LEN(default_iProduct_length)}, + {NULL, 0}, +}; + +static USBCompositePart** parts; +static uint32 numParts; +static DEVICE saved_Device_Table; +static DEVICE_PROP saved_Device_Property; +static USER_STANDARD_REQUESTS saved_User_Standard_Requests; + +static void (*ep_int_in[7])(void); +static void (*ep_int_out[7])(void); + +uint8 usb_generic_set_parts(USBCompositePart** _parts, unsigned _numParts) { + parts = _parts; + numParts = _numParts; + unsigned numInterfaces = 0; + unsigned numEndpoints = 1; + uint16 usbDescriptorSize = 0; + uint16 pmaOffset = USB_EP0_RX_BUFFER_ADDRESS + USB_EP0_BUFFER_SIZE; + + for (unsigned i = 0 ; i < 7 ; i++) { + ep_int_in[i] = NOP_Process; + ep_int_out[i] = NOP_Process; + } + + usbDescriptorSize = 0; + for (unsigned i = 0 ; i < _numParts ; i++ ) { + parts[i]->startInterface = numInterfaces; + numInterfaces += parts[i]->numInterfaces; + if (numEndpoints + parts[i]->numEndpoints > 8) { + return 0; + } + if (usbDescriptorSize + parts[i]->descriptorSize > MAX_USB_DESCRIPTOR_DATA_SIZE) { + return 0; + } + parts[i]->startEndpoint = numEndpoints; + USBEndpointInfo* ep = parts[i]->endpoints; + for (unsigned j = 0 ; j < parts[i]->numEndpoints ; j++) { + if (ep[j].bufferSize + pmaOffset > PMA_MEMORY_SIZE) { + return 0; + } + ep[j].pmaAddress = pmaOffset; + pmaOffset += ep[j].bufferSize; + ep[j].address = numEndpoints; + if (ep[j].callback == NULL) + ep[j].callback = NOP_Process; + if (ep[j].tx) { + ep_int_in[numEndpoints - 1] = ep[j].callback; + } + else { + ep_int_out[numEndpoints - 1] = ep[j].callback; + } + numEndpoints++; + } + parts[i]->getPartDescriptor(usbConfig.descriptorData + usbDescriptorSize); + usbDescriptorSize += parts[i]->descriptorSize; + } + + usbConfig.Config_Header = Base_Header; + usbConfig.Config_Header.bNumInterfaces = numInterfaces; + usbConfig.Config_Header.wTotalLength = usbDescriptorSize + sizeof(Base_Header); + Config_Descriptor.Descriptor_Size = usbConfig.Config_Header.wTotalLength; + + my_Device_Table.Total_Endpoint = numEndpoints; + + return 1; +} + +void usb_generic_set_info( uint16 idVendor, uint16 idProduct, const uint8* iManufacturer, const uint8* iProduct, const uint8* iSerialNumber) { + if (idVendor != 0) + usbGenericDescriptor_Device.idVendor = idVendor; + else + usbGenericDescriptor_Device.idVendor = LEAFLABS_ID_VENDOR; + + if (idProduct != 0) + usbGenericDescriptor_Device.idProduct = idProduct; + else + usbGenericDescriptor_Device.idProduct = MAPLE_ID_PRODUCT; + + if (iManufacturer == NULL) { + iManufacturer = (uint8*)&usb_generic_default_iManufacturer; + } + + String_Descriptor[1].Descriptor = (uint8*)iManufacturer; + String_Descriptor[1].Descriptor_Size = iManufacturer[0]; + + if (iProduct == NULL) { + iProduct = (uint8*)&usb_generic_default_iProduct; + } + + String_Descriptor[2].Descriptor = (uint8*)iProduct; + String_Descriptor[2].Descriptor_Size = iProduct[0]; + + if (iSerialNumber == NULL) { + numStringDescriptors = 3; + usbGenericDescriptor_Device.iSerialNumber = 0; + } + else { + String_Descriptor[3].Descriptor = (uint8*)iSerialNumber; + String_Descriptor[3].Descriptor_Size = iSerialNumber[0]; + numStringDescriptors = 4; + usbGenericDescriptor_Device.iSerialNumber = 3; + } +} + +void usb_generic_enable(void) { + /* Present ourselves to the host. Writing 0 to "disc" pin must + * pull USB_DP pin up while leaving USB_DM pulled down by the + * transceiver. See USB 2.0 spec, section 7.1.7.3. */ + +#ifdef GENERIC_BOOTLOADER + //Reset the USB interface on generic boards - developed by Victor PV + gpio_set_mode(GPIOA, 12, GPIO_OUTPUT_PP); + gpio_write_bit(GPIOA, 12, 0); + + for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed + gpio_set_mode(GPIOA, 12, GPIO_INPUT_FLOATING); +#endif + + if (BOARD_USB_DISC_DEV != NULL) { + gpio_set_mode(BOARD_USB_DISC_DEV, (uint8)(uint32)BOARD_USB_DISC_BIT, GPIO_OUTPUT_PP); + gpio_write_bit(BOARD_USB_DISC_DEV, (uint8)(uint32)BOARD_USB_DISC_BIT, 0); + } + + saved_Device_Table = Device_Table; + saved_Device_Property = Device_Property; + saved_User_Standard_Requests = User_Standard_Requests; + Device_Table = my_Device_Table; + Device_Property = my_Device_Property; + User_Standard_Requests = my_User_Standard_Requests; + + /* Initialize the USB peripheral. */ + usb_init_usblib(USBLIB, ep_int_in, ep_int_out); +} + +static void usbInit(void) { + pInformation->Current_Configuration = 0; + + USB_BASE->CNTR = USB_CNTR_FRES; + + USBLIB->irq_mask = 0; + USB_BASE->CNTR = USBLIB->irq_mask; + USB_BASE->ISTR = 0; + USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + USB_BASE->CNTR = USBLIB->irq_mask; + + USB_BASE->ISTR = 0; + USBLIB->irq_mask = USB_ISR_MSK; + USB_BASE->CNTR = USBLIB->irq_mask; + + nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + + for (unsigned i = 0 ; i < numParts ; i++) + if(parts[i]->usbInit != NULL) + parts[i]->usbInit(); + + USBLIB->state = USB_UNCONNECTED; +} + +#define BTABLE_ADDRESS 0x00 + +static void usbReset(void) { + pInformation->Current_Configuration = 0; + + /* current feature is current bmAttributes */ + pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED); + + USB_BASE->BTABLE = BTABLE_ADDRESS; + + /* setup control endpoint 0 */ + usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL); + usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL); + usb_set_ep_rx_addr(USB_EP0, USB_EP0_RX_BUFFER_ADDRESS); + usb_set_ep_tx_addr(USB_EP0, USB_EP0_TX_BUFFER_ADDRESS); + usb_clear_status_out(USB_EP0); + + usb_set_ep_rx_count(USB_EP0, USB_EP0_BUFFER_SIZE); + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + + for (unsigned i = 0 ; i < numParts ; i++) { + for (unsigned j = 0 ; j < parts[i]->numEndpoints ; j++) { + USBEndpointInfo* e = &(parts[i]->endpoints[j]); + uint8 address = e->address; + usb_set_ep_type(address, e->type); + if (parts[i]->endpoints[j].tx) { + usb_set_ep_tx_addr(address, e->pmaAddress); + usb_set_ep_tx_stat(address, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(address, USB_EP_STAT_RX_DISABLED); + } + else { + usb_set_ep_rx_addr(address, e->pmaAddress); + usb_set_ep_rx_count(address, e->bufferSize); + usb_set_ep_rx_stat(address, USB_EP_STAT_RX_VALID); + } + } + if (parts[i]->usbReset != NULL) + parts[i]->usbReset(); + } + + usbGenericTransmitting = -1; + + USBLIB->state = USB_ATTACHED; + SetDeviceAddress(0); + +} + +static void usb_power_down(void) { + USB_BASE->CNTR = USB_CNTR_FRES; + USB_BASE->ISTR = 0; + USB_BASE->CNTR = USB_CNTR_FRES + USB_CNTR_PDWN; +} + +void usb_generic_disable(void) { + /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0 + * spec, section 7.1.7.3). */ + nvic_irq_disable(NVIC_USB_LP_CAN_RX0); + + if (BOARD_USB_DISC_DEV != NULL) { + gpio_write_bit(BOARD_USB_DISC_DEV, (uint8)(uint32)BOARD_USB_DISC_BIT, 1); + } + + usb_power_down(); + + Device_Table = saved_Device_Table; + Device_Property = saved_Device_Property; + User_Standard_Requests = saved_User_Standard_Requests; +} + +static RESULT usbDataSetup(uint8 request) { + uint8* (*CopyRoutine)(uint16) = 0; + + if(Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT) && request == GET_DESCRIPTOR && + pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE){ + CopyRoutine = usbGetConfigDescriptor; + } + + if (CopyRoutine == NULL){ + for (unsigned i = 0 ; i < numParts ; i++) { + RESULT r = parts[i]->usbDataSetup(request); + if (USB_UNSUPPORT != r) + return r; + } + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +} + +static RESULT usbNoDataSetup(uint8 request) { + for (unsigned i = 0 ; i < numParts ; i++) { + RESULT r = parts[i]->usbNoDataSetup(request); + if (USB_UNSUPPORT != r) + return r; + } + + return USB_UNSUPPORT; +} + +static void usbSetConfiguration(void) { + if (pInformation->Current_Configuration != 0) { + USBLIB->state = USB_CONFIGURED; + } + for (unsigned i = 0 ; i < numParts ; i++) { + if (parts[i]->usbSetConfiguration != NULL) + parts[i]->usbSetConfiguration(); + } +} + +static void usbClearFeature(void) { + for (unsigned i = 0 ; i < numParts ; i++) { + if (parts[i]->usbClearFeature != NULL) + parts[i]->usbClearFeature(); + } +} + +static void usbSetDeviceAddress(void) { + USBLIB->state = USB_ADDRESSED; +} + +static uint8* usbGetDeviceDescriptor(uint16 length) { + return Standard_GetDescriptorData(length, &Device_Descriptor); +} + +static uint8* usbGetConfigDescriptor(uint16 length) { + return Standard_GetDescriptorData(length, &Config_Descriptor); +} + +static uint8* usbGetStringDescriptor(uint16 length) { + uint8 wValue0 = pInformation->USBwValue0; + + if (wValue0 >= numStringDescriptors) { + return NULL; + } + return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); +} + + +static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) { + if (alt_setting > 0) { + return USB_UNSUPPORT; + } else if (interface >= usbConfig.Config_Header.bNumInterfaces) { + return USB_UNSUPPORT; + } + + return USB_SUCCESS; +} + +void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) { + uint16 *dst = (uint16*)usb_pma_ptr(pma_offset); + uint16 n = len >> 1; + uint16 i; + for (i = 0; i < n; i++) { + *dst = (uint16)(*buf) | *(buf + 1) << 8; + buf += 2; + dst += 2; + } + if (len & 1) { + *dst = *buf; + } +} + +void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { + uint32 *src = (uint32*)usb_pma_ptr(pma_offset); + uint16 *dst = (uint16*)buf; + uint16 n = len >> 1; + uint16 i; + for (i = 0; i < n; i++) { + *dst++ = *src++; + } + if (len & 1) { + *dst = *src & 0xFF; + } +} + diff --git a/STM32F1/libraries/USBComposite/usb_generic.h b/STM32F1/libraries/USBComposite/usb_generic.h new file mode 100644 index 0000000..d665d8f --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_generic.h @@ -0,0 +1,60 @@ +#ifndef _USB_GENERIC_H +#define _USB_GENERIC_H +#include +typedef unsigned short u16; +typedef unsigned char u8; +#include +#include + +#define PMA_MEMORY_SIZE 512 +#define MAX_USB_DESCRIPTOR_DATA_SIZE 200 + +#define USB_EP0_BUFFER_SIZE 0x40 +#define USB_EP0_TX_BUFFER_ADDRESS 0x40 +#define USB_EP0_RX_BUFFER_ADDRESS (USB_EP0_TX_BUFFER_ADDRESS+USB_EP0_BUFFER_SIZE) + +#ifdef __cplusplus +extern "C" { +#endif + +extern const usb_descriptor_string usb_generic_default_iManufacturer; +extern const usb_descriptor_string usb_generic_default_iProduct; + +typedef struct USBEndpointInfo { + void (*callback)(void); + uint16 bufferSize; + uint16 type; // bulk, interrupt, etc. + uint8 tx; // 1 if TX, 0 if RX + uint8 address; + uint16 pmaAddress; +} USBEndpointInfo; + +typedef struct USBCompositePart { + uint8 numInterfaces; + uint8 numEndpoints; + uint8 startInterface; + uint8 startEndpoint; + uint16 descriptorSize; + void (*getPartDescriptor)(uint8* out); + void (*usbInit)(void); + void (*usbReset)(void); + void (*usbSetConfiguration)(void); + void (*usbClearFeature)(void); + RESULT (*usbDataSetup)(uint8 request); + RESULT (*usbNoDataSetup)(uint8 request); + USBEndpointInfo* endpoints; +} USBCompositePart; + +void usb_generic_set_info(uint16 idVendor, uint16 idProduct, const uint8* iManufacturer, const uint8* iProduct, const uint8* iSerialNumber); +uint8 usb_generic_set_parts(USBCompositePart** _parts, unsigned _numParts); +void usb_generic_disable(void); +void usb_generic_enable(void); +extern volatile int8 usbGenericTransmitting; +void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset); +void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_hid.c b/STM32F1/libraries/USBComposite/usb_hid.c new file mode 100644 index 0000000..162cd4a --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_hid.c @@ -0,0 +1,578 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usb/stm32f1/usb_hid.c + * @brief USB HID (human interface device) support + * + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include "usb_hid.h" +#include +#include +#include +#include + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" + +uint16 GetEPTxAddr(uint8 /*bEpNum*/); + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +static uint32 ProtocolValue = 0; + +static void hidDataTxCb(void); +static void hidUSBReset(void); +static RESULT hidUSBDataSetup(uint8 request); +static RESULT hidUSBNoDataSetup(uint8 request); +//static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); +static uint8* HID_GetReportDescriptor(uint16 Length); +static uint8* HID_GetProtocolValue(uint16 Length); + +static volatile HIDBuffer_t hidBuffers[MAX_HID_BUFFERS] = {{ 0 }}; +static volatile HIDBuffer_t* currentHIDBuffer = NULL; + +//#define DUMMY_BUFFER_SIZE 0x40 // at least as big as a buffer size + +#define HID_INTERFACE_OFFSET 0x00 +#define NUM_HID_ENDPOINTS 1 +#define HID_INTERFACE_NUMBER (HID_INTERFACE_OFFSET+usbHIDPart.startInterface) + +/* + * Descriptors + */ + +static ONE_DESCRIPTOR HID_Report_Descriptor = { + (uint8*)NULL, + 0 +}; + + +#define HID_ENDPOINT_TX 0 + +typedef struct { + //HID + usb_descriptor_interface HID_Interface; + HIDDescriptor HID_Descriptor; + usb_descriptor_endpoint HIDDataInEndpoint; +} __packed hid_part_config; + +static const hid_part_config hidPartConfigData = { + .HID_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = HID_INTERFACE_OFFSET, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = NUM_HID_ENDPOINTS, + .bInterfaceClass = USB_INTERFACE_CLASS_HID, + .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_HID, + .bInterfaceProtocol = 0x00, /* Common AT Commands */ + .iInterface = 0x00, + }, + .HID_Descriptor = { + .len = 9,//sizeof(HIDDescDescriptor), + .dtype = HID_DESCRIPTOR_TYPE, + .versionL = 0x10, + .versionH = 0x01, + .country = 0x00, + .numDesc = 0x01, + .desctype = REPORT_DESCRIPTOR,//0x22, + .descLenL = 0x00, //PATCH + .descLenH = 0x00, //PATCH + }, + .HIDDataInEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = USB_DESCRIPTOR_ENDPOINT_IN | HID_ENDPOINT_TX, // PATCH + .bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT, + .wMaxPacketSize = USB_HID_TX_EPSIZE,//0x40,//big enough for a keyboard 9 byte packet and for a mouse 5 byte packet + .bInterval = 0x0A, + } +}; + +static USBEndpointInfo hidEndpoints[1] = { + { + .callback = hidDataTxCb, + .bufferSize = USB_HID_TX_EPSIZE, + .type = USB_EP_EP_TYPE_INTERRUPT, // TODO: interrupt??? + .tx = 1, + } +}; + +#define OUT_BYTE(s,v) out[(uint8*)&(s.v)-(uint8*)&s] + +static void getHIDPartDescriptor(uint8* out) { + memcpy(out, &hidPartConfigData, sizeof(hid_part_config)); + // patch to reflect where the part goes in the descriptor + OUT_BYTE(hidPartConfigData, HID_Interface.bInterfaceNumber) += usbHIDPart.startInterface; + OUT_BYTE(hidPartConfigData, HIDDataInEndpoint.bEndpointAddress) += usbHIDPart.startEndpoint; + OUT_BYTE(hidPartConfigData, HID_Descriptor.descLenL) = (uint8)HID_Report_Descriptor.Descriptor_Size; + OUT_BYTE(hidPartConfigData, HID_Descriptor.descLenH) = (uint8)(HID_Report_Descriptor.Descriptor_Size>>8); +} + +USBCompositePart usbHIDPart = { + .numInterfaces = 1, + .numEndpoints = sizeof(hidEndpoints)/sizeof(*hidEndpoints), + .descriptorSize = sizeof(hid_part_config), + .getPartDescriptor = getHIDPartDescriptor, + .usbInit = NULL, + .usbReset = hidUSBReset, + .usbDataSetup = hidUSBDataSetup, + .usbNoDataSetup = hidUSBNoDataSetup, + .usbClearFeature = NULL, + .usbSetConfiguration = NULL, + .endpoints = hidEndpoints +}; + + +#define HID_TX_BUFFER_SIZE 256 // must be power of 2 +#define HID_TX_BUFFER_SIZE_MASK (HID_TX_BUFFER_SIZE-1) +// Tx data +static volatile uint8 hidBufferTx[HID_TX_BUFFER_SIZE]; +// Write index to hidBufferTx +static volatile uint32 hid_tx_head = 0; +// Read index from hidBufferTx +static volatile uint32 hid_tx_tail = 0; + +#define CDC_SERIAL_RX_BUFFER_SIZE 256 // must be power of 2 +#define CDC_SERIAL_RX_BUFFER_SIZE_MASK (CDC_SERIAL_RX_BUFFER_SIZE-1) + + + + +void usb_hid_putc(char ch) { + while (!usb_hid_tx((uint8*)&ch, 1)) + ; +} + + /* +static void hidStatusIn() { + if (pInformation->ControlState == WAIT_STATUS_IN) { + if (currentInFeature >= 0) { + if (featureBuffers[currentInFeature].bufferSize == featureBuffers[currentInFeature].currentDataSize) + featureBuffers[currentInFeature].state = HID_BUFFER_UNREAD; + currentInFeature = -1; + } + if (currentOutput >= 0) { + if (outputBuffers[currentOutput].bufferSize == outputBuffers[currentOutput].currentDataSize) + outputBuffers[currentOutput].state = HID_BUFFER_UNREAD; + currentOutput = -1; + } + } +} + */ + +void usb_hid_set_report_descriptor(const uint8* report_descriptor, uint16 report_descriptor_length) { + HID_Report_Descriptor.Descriptor = (uint8*)report_descriptor; + HID_Report_Descriptor.Descriptor_Size = report_descriptor_length; +} + + +static volatile HIDBuffer_t* usb_hid_find_buffer(uint8 type, uint8 reportID) { + uint8 typeTest = type == HID_REPORT_TYPE_OUTPUT ? HID_BUFFER_MODE_OUTPUT : 0; + for (int i=0; ibuffer+delta, data, buffer->bufferSize-delta); + if (reportID) + buffer->buffer[0] = reportID; + buffer->currentDataSize = buffer->bufferSize; + buffer->state = HID_BUFFER_READ; + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + return; + } +} + +static uint8 have_unread_data_in_hid_buffer() { + for (int i=0;ireportID == reportID && buffer->state != HID_BUFFER_EMPTY && !(poll && buffer->state == HID_BUFFER_READ)) { + if (buffer->bufferSize != buffer->currentDataSize) { + buffer->state = HID_BUFFER_EMPTY; + ret = 0; + } + else { + unsigned delta = reportID != 0; + if (out != NULL) + memcpy(out, (uint8*)buffer->buffer+delta, buffer->bufferSize-delta); + + if (poll) { + buffer->state = HID_BUFFER_READ; + } + + ret = buffer->bufferSize-delta; + } + } + + if (! have_unread_data_in_hid_buffer() ) { + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + } + + nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + + return ret; +} + +void usb_hid_clear_buffers(uint8 type) { + uint8 typeTest = type == HID_REPORT_TYPE_OUTPUT ? HID_BUFFER_MODE_OUTPUT : 0; + for (int i=0; imode |= HID_BUFFER_MODE_OUTPUT; + else + buf->mode &= ~HID_BUFFER_MODE_OUTPUT; + memset((void*)buf->buffer, 0, buf->bufferSize); + buf->buffer[0] = buf->reportID; + + volatile HIDBuffer_t* buffer = usb_hid_find_buffer(type, buf->reportID); + + if (buffer != NULL) { + *buffer = *buf; + return 1; + } + else { + for (int i=0; i (HID_TX_BUFFER_SIZE-tx_unsent-1) ) { + len = (HID_TX_BUFFER_SIZE-tx_unsent-1); + } + if (len==0) return 0; // buffer full + + uint16 i; + // copy data from user buffer to USB Tx buffer + for (i=0; i= 0); + + if (usbGenericTransmitting<0) { + hidDataTxCb(); // initiate data transmission + } + + return len; +} + + + +uint16 usb_hid_get_pending(void) { + return (hid_tx_head - hid_tx_tail) & HID_TX_BUFFER_SIZE_MASK; +} + +static void hidDataTxCb(void) +{ + uint32 tail = hid_tx_tail; // load volatile variable + uint32 tx_unsent = (hid_tx_head - tail) & HID_TX_BUFFER_SIZE_MASK; + if (tx_unsent==0) { + if ( (--usbGenericTransmitting)==0) goto flush_hid; // no more data to send + return; // it was already flushed, keep Tx endpoint disabled + } + usbGenericTransmitting = 1; + // We can only send up to USBHID_CDCACM_TX_EPSIZE bytes in the endpoint. + if (tx_unsent > USB_HID_TX_EPSIZE) { + tx_unsent = USB_HID_TX_EPSIZE; + } + // copy the bytes from USB Tx buffer to PMA buffer + uint32 *dst = usb_pma_ptr(usbHIDPart.endpoints[HID_ENDPOINT_TX].pmaAddress); + uint16 tmp = 0; + uint16 val; + unsigned i; + for (i = 0; i < tx_unsent; i++) { + val = hidBufferTx[tail]; + tail = (tail + 1) & HID_TX_BUFFER_SIZE_MASK; + if (i&1) { + *dst++ = tmp | (val<<8); + } else { + tmp = val; + } + } + if ( tx_unsent&1 ) { + *dst = tmp; + } + hid_tx_tail = tail; // store volatile variable + +flush_hid: + // enable Tx endpoint + usb_set_ep_tx_count(usbHIDPart.endpoints[HID_ENDPOINT_TX].address, tx_unsent); + usb_set_ep_tx_stat(usbHIDPart.endpoints[HID_ENDPOINT_TX].address, USB_EP_STAT_TX_VALID); +} + + + +static void hidUSBReset(void) { + /* Reset the RX/TX state */ + hid_tx_head = 0; + hid_tx_tail = 0; + + currentHIDBuffer = NULL; +} + +static uint8* HID_Set(uint16 length) { + if (currentHIDBuffer == NULL) + return NULL; + + if (length ==0) { + if ( (0 == (currentHIDBuffer->mode & HID_BUFFER_MODE_NO_WAIT)) && + currentHIDBuffer->state == HID_BUFFER_UNREAD && + pInformation->Ctrl_Info.Usb_wOffset < pInformation->USBwLengths.w) { + pInformation->Ctrl_Info.Usb_wLength = 0xFFFF; + return NULL; + } + + uint16 len = pInformation->USBwLengths.w; + if (len > currentHIDBuffer->bufferSize) + len = currentHIDBuffer->bufferSize; + + currentHIDBuffer->currentDataSize = len; + + currentHIDBuffer->state = HID_BUFFER_EMPTY; + + if (pInformation->Ctrl_Info.Usb_wOffset < len) { + pInformation->Ctrl_Info.Usb_wLength = len - pInformation->Ctrl_Info.Usb_wOffset; + } + else { + pInformation->Ctrl_Info.Usb_wLength = 0; + } + + return NULL; + } + + if (pInformation->USBwLengths.w <= pInformation->Ctrl_Info.Usb_wOffset + pInformation->Ctrl_Info.PacketSize) { + currentHIDBuffer->state = HID_BUFFER_UNREAD; + } + + return (uint8*)currentHIDBuffer->buffer + pInformation->Ctrl_Info.Usb_wOffset; +} + +static uint8* HID_GetFeature(uint16 length) { + if (currentHIDBuffer == NULL) + return NULL; + + unsigned wOffset = pInformation->Ctrl_Info.Usb_wOffset; + + if (length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = currentHIDBuffer->bufferSize - wOffset; + return NULL; + } + + return (uint8*)currentHIDBuffer->buffer + wOffset; +} + +static RESULT hidUSBDataSetup(uint8 request) { + uint8* (*CopyRoutine)(uint16) = 0; + + if (pInformation->USBwIndex0 != HID_INTERFACE_NUMBER) + return USB_UNSUPPORT; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch (request) { + case SET_REPORT: + if (pInformation->USBwValue1 == HID_REPORT_TYPE_FEATURE) { + volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_FEATURE, pInformation->USBwValue0); + + if (buffer == NULL) { + return USB_UNSUPPORT; + } + + if (0 == (buffer->mode & HID_BUFFER_MODE_NO_WAIT) && buffer->state == HID_BUFFER_UNREAD) { + return USB_NOT_READY; + } + else + { + currentHIDBuffer = buffer; + CopyRoutine = HID_Set; + } + } + else if (pInformation->USBwValue1 == HID_REPORT_TYPE_OUTPUT) { + volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_OUTPUT, pInformation->USBwValue0); + + if (buffer == NULL) { + return USB_UNSUPPORT; + } + + if (0 == (buffer->mode & HID_BUFFER_MODE_NO_WAIT) && buffer->state == HID_BUFFER_UNREAD) { + return USB_NOT_READY; + } + else + { + currentHIDBuffer = buffer; + CopyRoutine = HID_Set; + } + } + break; + case GET_REPORT: + if (pInformation->USBwValue1 == HID_REPORT_TYPE_FEATURE) { + volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_FEATURE, pInformation->USBwValue0); + + if (buffer == NULL || buffer->state == HID_BUFFER_EMPTY) { + return USB_UNSUPPORT; + } + + currentHIDBuffer = buffer; + CopyRoutine = HID_GetFeature; + break; + } + default: + break; + } + } + + if(Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)){ + switch (request){ + case GET_DESCRIPTOR: + if (pInformation->USBwValue1 == REPORT_DESCRIPTOR){ + CopyRoutine = HID_GetReportDescriptor; + } + break; + case GET_PROTOCOL: // TODO: check for interface number? + CopyRoutine = HID_GetProtocolValue; + break; + } + } + + if (CopyRoutine == NULL){ + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +} + +static RESULT hidUSBNoDataSetup(uint8 request) { + if (pInformation->USBwIndex0 != HID_INTERFACE_NUMBER) + return USB_UNSUPPORT; + + RESULT ret = USB_UNSUPPORT; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch(request) { + case SET_PROTOCOL: + ProtocolValue = pInformation->USBwValue0; + ret = USB_SUCCESS; + break; + } + } + return ret; +} + +/* +static RESULT HID_SetProtocol(void){ + uint8 wValue0 = pInformation->USBwValue0; + ProtocolValue = wValue0; + return USB_SUCCESS; +} +*/ +static uint8* HID_GetProtocolValue(uint16 Length){ + if (Length == 0){ + pInformation->Ctrl_Info.Usb_wLength = 1; + return NULL; + } else { + return (uint8 *)(&ProtocolValue); + } +} + +static uint8* HID_GetReportDescriptor(uint16 Length){ + return Standard_GetDescriptorData(Length, &HID_Report_Descriptor); +} + diff --git a/STM32F1/libraries/USBComposite/usb_hid.h b/STM32F1/libraries/USBComposite/usb_hid.h new file mode 100644 index 0000000..856fd3e --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_hid.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/usb_device.h + * @brief USB Composite with CDC ACM and HID support + * + * IMPORTANT: this API is unstable, and may change without notice. + */ + +#ifndef _USB_HID_H_ +#define _USB_HID_H_ + +#include +#include +#include "usb_generic.h" + +#define MAX_HID_BUFFERS 8 +#define HID_BUFFER_SIZE(n,reportID) ((n)+((reportID)!=0)) +#define HID_BUFFER_ALLOCATE_SIZE(n,reportID) ((HID_BUFFER_SIZE((n),(reportID))+1)/2*2) + +#define HID_BUFFER_MODE_NO_WAIT 1 +#define HID_BUFFER_MODE_OUTPUT 2 + +#define HID_BUFFER_EMPTY 0 +#define HID_BUFFER_UNREAD 1 +#define HID_BUFFER_READ 2 + +extern USBCompositePart usbHIDPart; + +typedef struct HIDBuffer_t { + volatile uint8_t* buffer; // use HID_BUFFER_ALLOCATE_SIZE() to calculate amount of memory to allocate + uint16_t bufferSize; // this should match HID_BUFFER_SIZE + uint8_t reportID; + uint8_t mode; + uint16_t currentDataSize; + uint8_t state; // HID_BUFFER_EMPTY, etc. +#ifdef __cplusplus + inline HIDBuffer_t(volatile uint8_t* _buffer=NULL, uint16_t _bufferSize=0, uint8_t _reportID=0, uint8_t _mode=0) { + reportID = _reportID; + buffer = _buffer; + bufferSize = _bufferSize; + mode = _mode; + } +#endif +} HIDBuffer_t; + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_HID_TX_EPSIZE 0x40 + +void usb_hid_set_report_descriptor(const uint8* report_descriptor, uint16 report_descriptor_length); +void usb_hid_clear_buffers(uint8_t type); +uint8_t usb_hid_add_buffer(uint8_t type, volatile HIDBuffer_t* buf); +void usb_hid_set_buffers(uint8_t type, volatile HIDBuffer_t* featureBuffers, int count); +uint16_t usb_hid_get_data(uint8_t type, uint8_t reportID, uint8_t* out, uint8_t poll); +void usb_hid_set_feature(uint8_t reportID, uint8_t* data); + + + +/* + * HID Requests + */ + +typedef enum _HID_REQUESTS +{ + + GET_REPORT = 1, + GET_IDLE, + GET_PROTOCOL, + + SET_REPORT = 9, + SET_IDLE, + SET_PROTOCOL + +} HID_REQUESTS; + +#define HID_REPORT_TYPE_INPUT 0x01 +#define HID_REPORT_TYPE_OUTPUT 0x02 +#define HID_REPORT_TYPE_FEATURE 0x03 + + +/* + * HID Descriptors, etc. + */ + +#define HID_ENDPOINT_INT 1 + +#define HID_DESCRIPTOR_TYPE 0x21 +#define REPORT_DESCRIPTOR 0x22 + + +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t numDesc; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; +} HIDDescriptor; + + +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 + +#define USB_INTERFACE_CLASS_HID 0x03 +#define USB_INTERFACE_SUBCLASS_HID 0x01 + + /* + * HID interface + */ + +void usb_hid_putc(char ch); +uint32 usb_hid_tx(const uint8* buf, uint32 len); +uint32 usb_hid_tx_mod(const uint8* buf, uint32 len); + +uint32 usb_hid_data_available(void); /* in RX buffer */ +uint16 usb_hid_get_pending(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_mass.c b/STM32F1/libraries/USBComposite/usb_mass.c new file mode 100644 index 0000000..5ef053e --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_mass.c @@ -0,0 +1,464 @@ +#include + +#include "usb_generic.h" +#include "usb_mass.h" +#include "usb_scsi.h" +#include "usb_mass_internal.h" + +#include +#include +#include + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" +#include "usb_regs.h" + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +static void usb_mass_bot_cbw_decode(); + +static void usb_mass_set_configuration(); +static void usb_mass_clear_feature(); +static RESULT usb_mass_data_setup(uint8 request); +static RESULT usb_mass_no_data_setup(uint8 request); +static void usb_mass_reset(); +static uint8_t* usb_mass_get_max_lun(uint16_t Length); +static void usb_mass_in(void); +static void usb_mass_out(void); +uint32_t usb_mass_sil_write(uint8_t* pBufferPointer, uint32_t wBufferSize); +uint32_t usb_mass_sil_read(uint8_t* pBufferPointer); + +#define MASS_INTERFACE_OFFSET 0x00 +#define MASS_INTERFACE_NUMBER (MASS_INTERFACE_OFFSET+usbMassPart.startInterface) + + +#define LUN_DATA_LENGTH 1 + +static uint32_t maxLun = 0; +static uint32_t deviceState = DEVICE_STATE_UNCONNECTED; +uint8_t usb_mass_botState = BOT_STATE_IDLE; +BulkOnlyCBW usb_mass_CBW; +BulkOnlyCSW usb_mass_CSW; +uint8_t usb_mass_bulkDataBuff[MAX_BULK_PACKET_SIZE]; +uint16_t usb_mass_dataLength; +static uint8_t inRequestPending; +static uint8_t outRequestPending; + +typedef struct mass_descriptor_config { +// usb_descriptor_config_header Config_Header; + usb_descriptor_interface MASS_Interface; + usb_descriptor_endpoint DataInEndpoint; + usb_descriptor_endpoint DataOutEndpoint; +} __packed mass_descriptor_config; + + +#define MAX_POWER (500 >> 1) +const mass_descriptor_config usbMassConfigDescriptor = { + /*.Config_Header = + { + .bLength = sizeof (usb_descriptor_config_header), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = sizeof (usb_descriptor_config), + .bNumInterfaces = 0x01, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELF_POWERED), + .bMaxPower = MAX_POWER, + }, */ + + .MASS_Interface = + { + .bLength = sizeof (usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x00, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = 8, // mass storage + .bInterfaceSubClass = 6, // SCSI + .bInterfaceProtocol = 0x50, // Bulk-Only + .iInterface = 0, + }, + + .DataInEndpoint = + { + .bLength = sizeof (usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | MASS_ENDPOINT_TX), // PATCH + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = MAX_BULK_PACKET_SIZE, + .bInterval = 0, + }, + + .DataOutEndpoint = + { + .bLength = sizeof (usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | MASS_ENDPOINT_RX), // PATCH + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = MAX_BULK_PACKET_SIZE, + .bInterval = 1, + } +}; + +USBEndpointInfo usbMassEndpoints[2] = { + { + .callback = usb_mass_in, + .bufferSize = MAX_BULK_PACKET_SIZE, + .type = USB_EP_EP_TYPE_BULK, + .tx = 1, + }, + { + .callback = usb_mass_out, + .bufferSize = MAX_BULK_PACKET_SIZE, + .type = USB_EP_EP_TYPE_BULK, + .tx = 0, + }, +}; + +#define OUT_BYTE(s,v) out[(uint8*)&(s.v)-(uint8*)&s] + +static void getMassPartDescriptor(uint8* out) { + memcpy(out, &usbMassConfigDescriptor, sizeof(mass_descriptor_config)); + // patch to reflect where the part goes in the descriptor + OUT_BYTE(usbMassConfigDescriptor, MASS_Interface.bInterfaceNumber) += usbMassPart.startInterface; + OUT_BYTE(usbMassConfigDescriptor, DataInEndpoint.bEndpointAddress) += usbMassPart.startEndpoint; + OUT_BYTE(usbMassConfigDescriptor, DataOutEndpoint.bEndpointAddress) += usbMassPart.startEndpoint; +} + + + +USBCompositePart usbMassPart = { + .numInterfaces = 1, + .numEndpoints = sizeof(usbMassEndpoints)/sizeof(*usbMassEndpoints), + .descriptorSize = sizeof(mass_descriptor_config), + .getPartDescriptor = getMassPartDescriptor, + .usbInit = NULL, + .usbReset = usb_mass_reset, + .usbDataSetup = usb_mass_data_setup, + .usbNoDataSetup = usb_mass_no_data_setup, + .usbClearFeature = usb_mass_clear_feature, + .usbSetConfiguration = usb_mass_set_configuration, + .endpoints = usbMassEndpoints +}; + +static void usb_mass_reset(void) { + usb_mass_mal_init(0); + + pInformation->Current_Configuration = 0; // TODO: remove? + + /* current feature is current bmAttributes */ + pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELF_POWERED); // usbMassConfigDescriptor.Config_Header.bmAttributes; // TODO: remove? + + deviceState = DEVICE_STATE_ATTACHED; + usb_mass_CBW.dSignature = BOT_CBW_SIGNATURE; + usb_mass_botState = BOT_STATE_IDLE; +} + +static void usb_mass_set_configuration(void) { + if (pInformation->Current_Configuration != 0) { + deviceState = USB_CONFIGURED; + ClearDTOG_TX(USB_MASS_TX_ENDP); + ClearDTOG_RX(USB_MASS_RX_ENDP); + usb_mass_botState = BOT_STATE_IDLE; + } +} + +static void usb_mass_clear_feature(void) { + /* when the host send a usb_mass_CBW with invalid signature or invalid length the two + Endpoints (IN & OUT) shall stall until receiving a Mass Storage Reset */ + if (usb_mass_CBW.dSignature != BOT_CBW_SIGNATURE) { + usb_mass_bot_abort(BOT_DIR_BOTH); + } +} + +static RESULT usb_mass_data_setup(uint8 request) { + uint8_t * (*copy_routine)(uint16_t); + + copy_routine = NULL; + if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + && (request == REQUEST_GET_MAX_LUN) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex == MASS_INTERFACE_NUMBER) && (pInformation->USBwLength == 0x01)) { + copy_routine = usb_mass_get_max_lun; + } else { + return USB_UNSUPPORT; + } + + if (copy_routine == NULL) { + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = copy_routine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*copy_routine)(0); + + return USB_SUCCESS; +} + +static uint8_t* usb_mass_get_max_lun(uint16_t length) { + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = LUN_DATA_LENGTH; + return 0; + } else { + return ((uint8_t*) (&maxLun)); + } +} + +static RESULT usb_mass_no_data_setup(uint8 request) { + if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + && (request == REQUEST_MASS_STORAGE_RESET) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex == MASS_INTERFACE_NUMBER) && (pInformation->USBwLength == 0x00)) { + + /* Initialize Endpoint 1 */ + ClearDTOG_TX(USB_MASS_TX_ENDP); + + /* Initialize Endpoint 2 */ + ClearDTOG_RX(USB_MASS_RX_ENDP); + + /*initialize the usb_mass_CBW signature to enable the clear feature*/ + usb_mass_CBW.dSignature = BOT_CBW_SIGNATURE; + usb_mass_botState = BOT_STATE_IDLE; + + return USB_SUCCESS; + } + return USB_UNSUPPORT; +} + + +void usb_mass_loop() { + if (inRequestPending) { + inRequestPending = 0; + + switch (usb_mass_botState) { + case BOT_STATE_CSW_Send: + case BOT_STATE_ERROR: + usb_mass_botState = BOT_STATE_IDLE; + SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); /* enable the Endpoint to receive the next cmd*/ + break; + case BOT_STATE_DATA_IN: + switch (usb_mass_CBW.CB[0]) { + case SCSI_READ10: + scsi_read10_cmd(usb_mass_CBW.bLUN, SCSI_lba, SCSI_blkLen); + break; + } + break; + case BOT_STATE_DATA_IN_LAST: + usb_mass_bot_set_csw(BOT_CSW_CMD_PASSED, BOT_SEND_CSW_ENABLE); + SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); + break; + + default: + break; + } + } + + if (outRequestPending) { + outRequestPending = 0; + + uint8_t CMD; + CMD = usb_mass_CBW.CB[0]; + + switch (usb_mass_botState) { + case BOT_STATE_IDLE: + usb_mass_bot_cbw_decode(); + break; + case BOT_STATE_DATA_OUT: + if (CMD == SCSI_WRITE10) { + scsi_write10_cmd(usb_mass_CBW.bLUN, SCSI_lba, SCSI_blkLen); + break; + } + usb_mass_bot_abort(BOT_DIR_OUT); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_PHASE_ERROR, BOT_SEND_CSW_DISABLE); + break; + default: + usb_mass_bot_abort(BOT_DIR_BOTH); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_PHASE_ERROR, BOT_SEND_CSW_DISABLE); + break; + } + } +} + +/* + * IN + */ +static void usb_mass_in(void) { + inRequestPending = 1; +} + +/* + * OUT + */ +static void usb_mass_out(void) { + usb_mass_dataLength = usb_mass_sil_read(usb_mass_bulkDataBuff); + outRequestPending = 1; +} + +static void usb_mass_bot_cbw_decode() { + uint32_t counter; + + for (counter = 0; counter < usb_mass_dataLength; counter++) { + *((uint8_t *) & usb_mass_CBW + counter) = usb_mass_bulkDataBuff[counter]; + } + usb_mass_CSW.dTag = usb_mass_CBW.dTag; + usb_mass_CSW.dDataResidue = usb_mass_CBW.dDataLength; + if (usb_mass_dataLength != BOT_CBW_PACKET_LENGTH) { + usb_mass_bot_abort(BOT_DIR_BOTH); + /* reset the usb_mass_CBW.dSignature to disable the clear feature until receiving a Mass storage reset*/ + usb_mass_CBW.dSignature = 0; + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_PARAMETER_LIST_LENGTH_ERROR); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + return; + } + + if ((usb_mass_CBW.CB[0] == SCSI_READ10) || (usb_mass_CBW.CB[0] == SCSI_WRITE10)) { + /* Calculate Logical Block Address */ + SCSI_lba = (usb_mass_CBW.CB[2] << 24) | (usb_mass_CBW.CB[3] << 16) | (usb_mass_CBW.CB[4] << 8) | usb_mass_CBW.CB[5]; + /* Calculate the Number of Blocks to transfer */ + SCSI_blkLen = (usb_mass_CBW.CB[7] << 8) | usb_mass_CBW.CB[8]; + } + + if (usb_mass_CBW.dSignature == BOT_CBW_SIGNATURE) { + /* Valid usb_mass_CBW */ + if ((usb_mass_CBW.bLUN > maxLun) || (usb_mass_CBW.bCBLength < 1) || (usb_mass_CBW.bCBLength > 16)) { + usb_mass_bot_abort(BOT_DIR_BOTH); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + } else { + switch (usb_mass_CBW.CB[0]) { + case SCSI_REQUEST_SENSE: + scsi_request_sense_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_INQUIRY: + scsi_inquiry_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_START_STOP_UNIT: + scsi_start_stop_unit_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_ALLOW_MEDIUM_REMOVAL: + scsi_start_stop_unit_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_MODE_SENSE6: + scsi_mode_sense6_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_MODE_SENSE10: + scsi_mode_sense10_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_READ_FORMAT_CAPACITIES: + scsi_read_format_capacity_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_READ_CAPACITY10: + scsi_read_capacity10_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_TEST_UNIT_READY: + scsi_test_unit_ready_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_READ10: + scsi_read10_cmd(usb_mass_CBW.bLUN, SCSI_lba, SCSI_blkLen); + break; + case SCSI_WRITE10: + scsi_write10_cmd(usb_mass_CBW.bLUN, SCSI_lba, SCSI_blkLen); + break; + case SCSI_VERIFY10: + scsi_verify10_cmd(usb_mass_CBW.bLUN); + break; + case SCSI_FORMAT_UNIT: + scsi_format_cmd(usb_mass_CBW.bLUN); + break; + + case SCSI_MODE_SELECT10: + case SCSI_MODE_SELECT6: + case SCSI_SEND_DIAGNOSTIC: + case SCSI_READ6: + case SCSI_READ12: + case SCSI_READ16: + case SCSI_READ_CAPACITY16: + case SCSI_WRITE6: + case SCSI_WRITE12: + case SCSI_VERIFY12: + case SCSI_VERIFY16: + case SCSI_WRITE16: + scsi_invalid_cmd(usb_mass_CBW.bLUN); + break; + + default: + { + usb_mass_bot_abort(BOT_DIR_BOTH); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + } + } + } + } else { + /* Invalid usb_mass_CBW */ + usb_mass_bot_abort(BOT_DIR_BOTH); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + } +} + +void usb_mass_bot_abort(uint8_t direction) { + switch (direction) { + case BOT_DIR_IN: + SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_STL); + break; + case BOT_DIR_OUT: + SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_STL); + break; + case BOT_DIR_BOTH: + SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_STL); + SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_STL); + break; + default: + break; + } +} + +void usb_mass_transfer_data_request(uint8_t* dataPointer, uint16_t dataLen) { + usb_mass_sil_write(dataPointer, dataLen); + + SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_VAL); + usb_mass_botState = BOT_STATE_DATA_IN_LAST; + usb_mass_CSW.dDataResidue -= dataLen; + usb_mass_CSW.bStatus = BOT_CSW_CMD_PASSED; +} + +void usb_mass_bot_set_csw(uint8_t status, uint8_t sendPermission) { + usb_mass_CSW.dSignature = BOT_CSW_SIGNATURE; + usb_mass_CSW.bStatus = status; + + usb_mass_sil_write(((uint8_t *) & usb_mass_CSW), BOT_CSW_DATA_LENGTH); + + usb_mass_botState = BOT_STATE_ERROR; + if (sendPermission) { + usb_mass_botState = BOT_STATE_CSW_Send; + SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_VAL); + } +} + +uint32_t usb_mass_sil_write(uint8_t* pBufferPointer, uint32_t wBufferSize) { + /* Use the memory interface function to write to the selected endpoint */ + usb_copy_to_pma(pBufferPointer, wBufferSize, USB_MASS_TX_ADDR); + + /* Update the data length in the control register */ + SetEPTxCount(USB_MASS_TX_ENDP, wBufferSize); + + return 0; +} + +uint32_t usb_mass_sil_read(uint8_t* pBufferPointer) { + uint32_t usb_mass_dataLength = 0; + + /* Get the number of received data on the selected Endpoint */ + usb_mass_dataLength = GetEPRxCount(USB_MASS_RX_ENDP); + + /* Use the memory interface function to write to the selected endpoint */ + usb_copy_from_pma(pBufferPointer, usb_mass_dataLength, USB_MASS_RX_ADDR); + + /* Return the number of received data */ + return usb_mass_dataLength; +} diff --git a/STM32F1/libraries/USBComposite/usb_mass.h b/STM32F1/libraries/USBComposite/usb_mass.h new file mode 100644 index 0000000..7d4f7ce --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_mass.h @@ -0,0 +1,112 @@ + +#ifndef _LIBMAPLE_USB_MASS_H_ +#define _LIBMAPLE_USB_MASS_H_ + +#include +#include +#include +#include +#include "usb_generic.h" +#include "usb_mass_mal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define N_STRING_DESCRIPTORS 4 + +#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ +#define MAX_BULK_PACKET_SIZE 0x40 /* 64B, max bulk Can't use 512 because the internal buffers for USB is only 512B */ + + + /* MASS Storage Requests */ +#define REQUEST_GET_MAX_LUN 0xFE +#define REQUEST_MASS_STORAGE_RESET 0xFF + + /* USB device state */ + typedef enum _DEVICE_STATE { + DEVICE_STATE_UNCONNECTED, + DEVICE_STATE_ATTACHED, + DEVICE_STATE_POWERED, + DEVICE_STATE_SUSPENDED, + DEVICE_STATE_ADDRESSED, + DEVICE_STATE_CONFIGURED + } DEVICE_STATE; + +#define BOT_DIR_IN 0 +#define BOT_DIR_OUT 1 +#define BOT_DIR_BOTH 2 + + /*****************************************************************************/ + /*********************** Bulk-Only Transfer State machine ********************/ + /*****************************************************************************/ +#define BOT_STATE_IDLE 0 /* Idle state */ +#define BOT_STATE_DATA_OUT 1 /* Data Out state */ +#define BOT_STATE_DATA_IN 2 /* Data In state */ +#define BOT_STATE_DATA_IN_LAST 3 /* Last Data In Last */ +#define BOT_STATE_CSW_Send 4 /* Command Status Wrapper */ +#define BOT_STATE_ERROR 5 /* error state */ + +#define BOT_CBW_SIGNATURE 0x43425355 +#define BOT_CSW_SIGNATURE 0x53425355 +#define BOT_CBW_PACKET_LENGTH 31 + +#define BOT_CSW_DATA_LENGTH 0x000D + + /* CSW Status Definitions */ +#define BOT_CSW_CMD_PASSED 0x00 +#define BOT_CSW_CMD_FAILED 0x01 +#define BOT_CSW_PHASE_ERROR 0x02 + +#define BOT_SEND_CSW_DISABLE 0 +#define BOT_SEND_CSW_ENABLE 1 + +#define USB_EP1_IN 0x81 + + /* Bulk-only Command Block Wrapper */ + typedef struct _BulkOnlyCBW { + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; + } BulkOnlyCBW; + + /* Bulk-only Command Status Wrapper */ + typedef struct _BulkOnlyCSW { + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; + } BulkOnlyCSW; + + typedef struct _usb_descriptor_config { + usb_descriptor_config_header Config_Header; + usb_descriptor_interface MASS_Interface; + usb_descriptor_endpoint DataInEndpoint; + usb_descriptor_endpoint DataOutEndpoint; + } __packed usb_descriptor_config; + + void usb_mass_enable(gpio_dev *disc_dev, uint8 disc_bit); + void usb_mass_disable(gpio_dev *disc_dev, uint8 disc_bit); + void usb_mass_loop(); + + void usb_mass_bot_set_csw(uint8_t cswStatus, uint8_t sendPermission); + void usb_mass_transfer_data_request(uint8_t* dataPointer, uint16_t dataLen); + void usb_mass_bot_abort(uint8_t direction); + + extern USBCompositePart usbMassPart; + +extern uint8_t usb_mass_botState; +extern BulkOnlyCBW usb_mass_CBW; +extern BulkOnlyCSW usb_mass_CSW; +extern uint8_t usb_mass_bulkDataBuff[MAX_BULK_PACKET_SIZE]; +extern uint16_t usb_mass_dataLength; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_mass_internal.h b/STM32F1/libraries/USBComposite/usb_mass_internal.h new file mode 100644 index 0000000..c3405a8 --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_mass_internal.h @@ -0,0 +1,12 @@ +#ifndef _USB_MASS_INTERNAL_H_ +#define _USB_MASS_INTERNAL_H_ + +extern USBEndpointInfo usbMassEndpoints[]; + +#define MASS_ENDPOINT_TX 0 +#define MASS_ENDPOINT_RX 1 +#define USB_MASS_RX_ENDP (usbMassEndpoints[MASS_ENDPOINT_RX].address) +#define USB_MASS_TX_ENDP (usbMassEndpoints[MASS_ENDPOINT_TX].address) +#define USB_MASS_RX_ADDR (usbMassEndpoints[MASS_ENDPOINT_RX].pmaAddress) +#define USB_MASS_TX_ADDR (usbMassEndpoints[MASS_ENDPOINT_TX].pmaAddress) +#endif \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/usb_mass_mal.c b/STM32F1/libraries/USBComposite/usb_mass_mal.c new file mode 100644 index 0000000..b3a79c3 --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_mass_mal.c @@ -0,0 +1,42 @@ +#include +#include "usb_mass_mal.h" + + +#define USB_MASS_MAL_FAIL 1 +#define USB_MASS_MAL_SUCCESS 0 + +MassStorageDriveInfo usb_mass_drives[USB_MASS_MAX_DRIVES] = { { 0 } }; + +uint16_t usb_mass_mal_init(uint8_t lun) { + if (lun >= USB_MASS_MAX_DRIVES || (usb_mass_drives[lun].init != NULL && ! usb_mass_drives[lun].init())) + return USB_MASS_MAL_FAIL; + else + return USB_MASS_MAL_SUCCESS; +} + +void usb_mass_mal_format(uint8_t lun) { + if (lun < USB_MASS_MAX_DRIVES && usb_mass_drives[lun].format != NULL) + usb_mass_drives[lun].format(); +} + +uint16_t usb_mass_mal_get_status(uint8_t lun) { + if (lun >= USB_MASS_MAX_DRIVES || (usb_mass_drives[lun].status != NULL && ! usb_mass_drives[lun].status())) + return USB_MASS_MAL_FAIL; + else + return USB_MASS_MAL_SUCCESS; +} + +uint16_t usb_mass_mal_read_memory(uint8_t lun, uint32_t memoryOffset, uint8_t *readbuff, uint16_t transferLength) { + if (lun >= USB_MASS_MAX_DRIVES || ! usb_mass_drives[lun].read(memoryOffset, readbuff, transferLength)) + return USB_MASS_MAL_FAIL; + else + return USB_MASS_MAL_SUCCESS; +} + +uint16_t usb_mass_mal_write_memory(uint8_t lun, uint32_t memoryOffset, uint8_t *writebuff, uint16_t transferLength) { + if (lun >= USB_MASS_MAX_DRIVES || usb_mass_drives[lun].write == NULL + || ! usb_mass_drives[lun].write(memoryOffset, writebuff, transferLength)) + return USB_MASS_MAL_FAIL; + else + return USB_MASS_MAL_SUCCESS; +} diff --git a/STM32F1/libraries/USBComposite/usb_mass_mal.h b/STM32F1/libraries/USBComposite/usb_mass_mal.h new file mode 100644 index 0000000..455fd71 --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_mass_mal.h @@ -0,0 +1,39 @@ +#ifndef __USB_MASS_MAL_H +#define __USB_MASS_MAL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_MASS_MAX_DRIVES 2 + +typedef bool (*MassStorageWriter)(uint32_t memoryOffset, const uint8_t *writebuff, uint16_t transferLength); +typedef bool (*MassStorageReader)(uint32_t memoryOffset, uint8_t *readbuff, uint16_t transferLength); +typedef bool (*MassStorageStatuser)(void); +typedef bool (*MassStorageInitializer)(void); +typedef bool (*MassStorageFormatter)(void); + +typedef struct { + uint32_t blockCount; + MassStorageReader read; + MassStorageWriter write; + MassStorageStatuser status; + MassStorageInitializer init; + MassStorageFormatter format; +} MassStorageDriveInfo; + +extern MassStorageDriveInfo usb_mass_drives[USB_MASS_MAX_DRIVES]; +uint16_t usb_mass_mal_init(uint8_t lun); +uint16_t usb_mass_mal_get_status(uint8_t lun); +uint16_t usb_mass_mal_read_memory(uint8_t lun, uint32_t memoryOffset, uint8_t *readbuff, uint16_t transferLength); +uint16_t usb_mass_mal_write_memory(uint8_t lun, uint32_t memoryOffset, uint8_t *writebuff, uint16_t transferLength); +void usb_mass_mal_format(uint8_t lun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_midi_device.c b/STM32F1/libraries/USBComposite/usb_midi_device.c new file mode 100644 index 0000000..f8a4fba --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_midi_device.c @@ -0,0 +1,533 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * Copyright (c) 2013 Magnus Lundin. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usb/stm32f1/usb_midi_device.c + * @brief USB MIDI. + * + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include +#include "usb_generic.h" +#include "usb_midi_device.h" +#include +#include + +#include +#include +#include + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +static void midiDataTxCb(void); +static void midiDataRxCb(void); + +static void usbMIDIReset(void); +static RESULT usbMIDIDataSetup(uint8 request); +static RESULT usbMIDINoDataSetup(uint8 request); + +#define MIDI_ENDPOINT_RX 0 +#define MIDI_ENDPOINT_TX 1 +#define USB_MIDI_RX_ENDP (midiEndpoints[MIDI_ENDPOINT_RX].address) +#define USB_MIDI_TX_ENDP (midiEndpoints[MIDI_ENDPOINT_TX].address) +#define USB_MIDI_RX_ADDR (midiEndpoints[MIDI_ENDPOINT_RX].pmaAddress) +#define USB_MIDI_TX_ADDR (midiEndpoints[MIDI_ENDPOINT_TX].pmaAddress) + +/* + * Descriptors + */ + +typedef struct { +// usb_descriptor_config_header Config_Header; + /* Control Interface */ + usb_descriptor_interface AC_Interface; + AC_CS_INTERFACE_DESCRIPTOR(1) AC_CS_Interface; + /* Control Interface */ + usb_descriptor_interface MS_Interface; + MS_CS_INTERFACE_DESCRIPTOR MS_CS_Interface; + MIDI_IN_JACK_DESCRIPTOR MIDI_IN_JACK_1; + MIDI_IN_JACK_DESCRIPTOR MIDI_IN_JACK_2; + MIDI_OUT_JACK_DESCRIPTOR(1) MIDI_OUT_JACK_3; + MIDI_OUT_JACK_DESCRIPTOR(1) MIDI_OUT_JACK_4; + usb_descriptor_endpoint DataOutEndpoint; + MS_CS_BULK_ENDPOINT_DESCRIPTOR(1) MS_CS_DataOutEndpoint; + usb_descriptor_endpoint DataInEndpoint; + MS_CS_BULK_ENDPOINT_DESCRIPTOR(1) MS_CS_DataInEndpoint; +} __packed usb_descriptor_config; + +static const usb_descriptor_config usbMIDIDescriptor_Config = { + /* .Config_Header = { + .bLength = sizeof(usb_descriptor_config_header), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = sizeof(usb_descriptor_config), + .bNumInterfaces = 0x02, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED), + .bMaxPower = MAX_POWER, + }, */ + + .AC_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x00, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x00, + .bInterfaceClass = USB_INTERFACE_CLASS_AUDIO, + .bInterfaceSubClass = USB_INTERFACE_AUDIOCONTROL, + .bInterfaceProtocol = 0x00, + .iInterface = 0x00, + }, + + .AC_CS_Interface = { + .bLength = AC_CS_INTERFACE_DESCRIPTOR_SIZE(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE, + .SubType = 0x01, + .bcdADC = 0x0100, + .wTotalLength = AC_CS_INTERFACE_DESCRIPTOR_SIZE(1), + .bInCollection = 0x01, + .baInterfaceNr = {0x01}, + }, + + .MS_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x01, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = USB_INTERFACE_CLASS_AUDIO, + .bInterfaceSubClass = USB_INTERFACE_MIDISTREAMING, + .bInterfaceProtocol = 0x00, + .iInterface = 0, // was 0x04 + }, + + .MS_CS_Interface = { + .bLength = sizeof(MS_CS_INTERFACE_DESCRIPTOR), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE, + .SubType = 0x01, + .bcdADC = 0x0100, + .wTotalLength = sizeof(MS_CS_INTERFACE_DESCRIPTOR) + +sizeof(MIDI_IN_JACK_DESCRIPTOR) + +sizeof(MIDI_IN_JACK_DESCRIPTOR) + +MIDI_OUT_JACK_DESCRIPTOR_SIZE(1) + +MIDI_OUT_JACK_DESCRIPTOR_SIZE(1) + +sizeof(usb_descriptor_endpoint) + +MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1) + +sizeof(usb_descriptor_endpoint) + +MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1) + /* 0x41-4 */, + }, + + .MIDI_IN_JACK_1 = { + .bLength = sizeof(MIDI_IN_JACK_DESCRIPTOR), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE, + .SubType = MIDI_IN_JACK, + .bJackType = MIDI_JACK_EMBEDDED, + .bJackId = 0x01, + .iJack = 0x05, + }, + + .MIDI_IN_JACK_2 = { + .bLength = sizeof(MIDI_IN_JACK_DESCRIPTOR), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE, + .SubType = MIDI_IN_JACK, + .bJackType = MIDI_JACK_EXTERNAL, + .bJackId = 0x02, + .iJack = 0x00, + }, + + .MIDI_OUT_JACK_3 = { + .bLength = MIDI_OUT_JACK_DESCRIPTOR_SIZE(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE, + .SubType = MIDI_OUT_JACK, + .bJackType = MIDI_JACK_EMBEDDED, + .bJackId = 0x03, + .bNrInputPins = 0x01, + .baSourceId = {0x02}, + .baSourcePin = {0x01}, + .iJack = 0x00, + }, + + .MIDI_OUT_JACK_4 = { + .bLength = MIDI_OUT_JACK_DESCRIPTOR_SIZE(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE, + .SubType = MIDI_OUT_JACK, + .bJackType = MIDI_JACK_EXTERNAL, +// .bJackId = 0x04, + .bJackId = 0x03, + .bNrInputPins = 0x01, + .baSourceId = {0x01}, + .baSourcePin = {0x01}, + .iJack = 0x00, + }, + + .DataOutEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | + MIDI_ENDPOINT_RX), // PATCH + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USB_MIDI_RX_EPSIZE, + .bInterval = 0x00, + }, + + .MS_CS_DataOutEndpoint = { + .bLength = MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_ENDPOINT, + .SubType = 0x01, + .bNumEmbMIDIJack = 0x01, + .baAssocJackID = {0x01}, + }, + + .DataInEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | MIDI_ENDPOINT_TX), // PATCH + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USB_MIDI_TX_EPSIZE, + .bInterval = 0x00, + }, + + .MS_CS_DataInEndpoint = { + .bLength = MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CS_ENDPOINT, + .SubType = 0x01, + .bNumEmbMIDIJack = 0x01, + .baAssocJackID = {0x03}, + }, + +}; + +/* I/O state */ + +/* Received data */ +static volatile uint32 midiBufferRx[USB_MIDI_RX_EPSIZE/4]; +/* Read index into midiBufferRx */ +static volatile uint32 rx_offset = 0; +/* Transmit data */ +static volatile uint32 midiBufferTx[USB_MIDI_TX_EPSIZE/4]; +/* Write index into midiBufferTx */ +static volatile uint32 tx_offset = 0; +/* Number of bytes left to transmit */ +static volatile uint32 n_unsent_packets = 0; +/* Are we currently sending an IN packet? */ +static volatile uint8 transmitting = 0; +/* Number of unread bytes */ +static volatile uint32 n_unread_packets = 0; + + +// eventually all of this should be in a place for settings which can be written to flash. +volatile uint8 myMidiChannel = DEFAULT_MIDI_CHANNEL; +volatile uint8 myMidiDevice = DEFAULT_MIDI_DEVICE; +volatile uint8 myMidiCable = DEFAULT_MIDI_CABLE; +volatile uint8 myMidiID[] = { LEAFLABS_MMA_VENDOR_1,LEAFLABS_MMA_VENDOR_2,LEAFLABS_MMA_VENDOR_3,0}; + +#define OUT_BYTE(s,v) out[(uint8*)&(s.v)-(uint8*)&s] + +static void getMIDIPartDescriptor(uint8* out) { + memcpy(out, &usbMIDIDescriptor_Config, sizeof(usbMIDIDescriptor_Config)); + // patch to reflect where the part goes in the descriptor + OUT_BYTE(usbMIDIDescriptor_Config, AC_Interface.bInterfaceNumber) += usbMIDIPart.startInterface; + OUT_BYTE(usbMIDIDescriptor_Config, MS_Interface.bInterfaceNumber) += usbMIDIPart.startInterface; + OUT_BYTE(usbMIDIDescriptor_Config, AC_CS_Interface.baInterfaceNr) += usbMIDIPart.startInterface; + OUT_BYTE(usbMIDIDescriptor_Config, DataOutEndpoint.bEndpointAddress) += usbMIDIPart.startEndpoint; + OUT_BYTE(usbMIDIDescriptor_Config, DataInEndpoint.bEndpointAddress) += usbMIDIPart.startEndpoint; +} + +static USBEndpointInfo midiEndpoints[2] = { + { + .callback = midiDataRxCb, + .bufferSize = USB_MIDI_RX_EPSIZE, + .type = USB_EP_EP_TYPE_BULK, + .tx = 0 + }, + { + .callback = midiDataTxCb, + .bufferSize = USB_MIDI_TX_EPSIZE, + .type = USB_EP_EP_TYPE_BULK, + .tx = 1, + } +}; + +USBCompositePart usbMIDIPart = { + .numInterfaces = 2, + .numEndpoints = sizeof(midiEndpoints)/sizeof(*midiEndpoints), + .descriptorSize = sizeof(usbMIDIDescriptor_Config), + .getPartDescriptor = getMIDIPartDescriptor, + .usbInit = NULL, + .usbReset = usbMIDIReset, + .usbDataSetup = usbMIDIDataSetup, + .usbNoDataSetup = usbMIDINoDataSetup, + .endpoints = midiEndpoints +}; + +/* + * MIDI interface + */ + +/* This function is non-blocking. + * + * It copies data from a usercode buffer into the USB peripheral TX + * buffer, and returns the number of bytes copied. */ +uint32 usb_midi_tx(const uint32* buf, uint32 packets) { + uint32 bytes=packets*4; + /* Last transmission hasn't finished, so abort. */ + if (usb_midi_is_transmitting()) { + /* Copy to TxBuffer */ + + return 0; /* return len */ + } + + /* We can only put USB_MIDI_TX_EPSIZE bytes in the buffer. */ + if (bytes > USB_MIDI_TX_EPSIZE) { + bytes = USB_MIDI_TX_EPSIZE; + packets=bytes/4; + } + + /* Queue bytes for sending. */ + if (packets) { + usb_copy_to_pma((uint8 *)buf, bytes, USB_MIDI_TX_ADDR); + } + // We still need to wait for the interrupt, even if we're sending + // zero bytes. (Sending zero-size packets is useful for flushing + // host-side buffers.) + usb_set_ep_tx_count(USB_MIDI_TX_ENDP, bytes); + n_unsent_packets = packets; + transmitting = 1; + usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_VALID); + + return packets; +} + +uint32 usb_midi_data_available(void) { + return n_unread_packets; +} + +uint8 usb_midi_is_transmitting(void) { + return transmitting; +} + +uint16 usb_midi_get_pending(void) { + return n_unsent_packets; +} + +/* Nonblocking byte receive. + * + * Copies up to len bytes from our private data buffer (*NOT* the PMA) + * into buf and deq's the FIFO. */ +uint32 usb_midi_rx(uint32* buf, uint32 packets) { + /* Copy bytes to buffer. */ + uint32 n_copied = usb_midi_peek(buf, packets); + + /* Mark bytes as read. */ + n_unread_packets -= n_copied; + rx_offset += n_copied; + + /* If all bytes have been read, re-enable the RX endpoint, which + * was set to NAK when the current batch of bytes was received. */ + if (n_unread_packets == 0) { + usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE); + usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID); + rx_offset = 0; + } + + return n_copied; +} + +/* Nonblocking byte lookahead. + * + * Looks at unread bytes without marking them as read. */ +uint32 usb_midi_peek(uint32* buf, uint32 packets) { + uint32 i; + if (packets > n_unread_packets) { + packets = n_unread_packets; + } + + for (i = 0; i < packets; i++) { + buf[i] = midiBufferRx[i + rx_offset]; + } + + return packets; +} + +/* + * Callbacks + */ + +static void midiDataTxCb(void) { + n_unsent_packets = 0; + transmitting = 0; +} + +static void midiDataRxCb(void) { + usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_NAK); + n_unread_packets = usb_get_ep_rx_count(USB_MIDI_RX_ENDP) / 4; + /* This copy won't overwrite unread bytes, since we've set the RX + * endpoint to NAK, and will only set it to VALID when all bytes + * have been read. */ + + usb_copy_from_pma((uint8*)midiBufferRx, n_unread_packets * 4, + USB_MIDI_RX_ADDR); + + // discard volatile + LglSysexHandler((uint32*)midiBufferRx,(uint32*)&rx_offset,(uint32*)&n_unread_packets); + + if (n_unread_packets == 0) { + usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE); + usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID); + rx_offset = 0; + } + +} + +static void usbMIDIReset(void) { + /* Reset the RX/TX state */ + n_unread_packets = 0; + n_unsent_packets = 0; + rx_offset = 0; +} + +static RESULT usbMIDIDataSetup(uint8 request) { + (void)request;//unused +#if 0 + uint8* (*CopyRoutine)(uint16) = 0; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + } + + if (CopyRoutine == NULL) { + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +#endif + return USB_UNSUPPORT; +} + +static RESULT usbMIDINoDataSetup(uint8 request) { + (void)request;//unused +#if 0 + RESULT ret = USB_UNSUPPORT; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + } + return ret; +#endif + return USB_UNSUPPORT; +} + +// .............THIS IS NOT WORKING YET................ +// send debugging information to +static uint8_t sysexbuffer[80]={CIN_SYSEX,0xF0,0x7D,0x33,CIN_SYSEX,0x33,0x00,0xf7}; // !!!bad hardcoded number foo !!! +uint8_t iSysHexLine(uint8_t rectype, uint16_t address, uint8_t *payload,uint8_t payloadlength, uint8_t *buffer); +void sendThroughSysex(char *printbuffer, int bufferlength) { + int n; + n = iSysHexLine(1, 0 , (uint8_t *) printbuffer, (uint8_t) bufferlength , sysexbuffer+6); + usb_midi_tx((uint32*)sysexbuffer,n/4); +} + +#define HIGHBYTE(x) ((uint8_t) (((x) >> 8) & 0x00ff) ) +#define LOWBYTE(x) ((uint8_t) ((x) & 0x00ff) ) +#define HIGHNIBBLE(x) ((((uint8_t)(x)) & 0xF0) >> 4) +#define LOWNIBBLE(x) (((uint8_t)(x)) & 0x0F) +#define HEXCHAR(c) ((c>9)?55+c:48+c) + + +uint8_t iSysHexLine(uint8_t rectype, uint16_t address, uint8_t *payload,uint8_t payloadlength, uint8_t *buffer) { + + int i=0; int j; int thirdone; + uint8_t n=0; + uint16_t checksum=0; + //uint16_t length=0; + + buffer[i++]=':'; + + checksum+=payloadlength; + buffer[i++]=HEXCHAR(HIGHNIBBLE(payloadlength)); + buffer[i++]=HEXCHAR(LOWNIBBLE(payloadlength)); + buffer[i++]=CIN_SYSEX; + + n=HIGHBYTE(address); + checksum+=n; + buffer[i++]=HEXCHAR(HIGHNIBBLE(n)); + buffer[i++]=HEXCHAR(LOWNIBBLE(n)); + + n=LOWBYTE(address); + checksum+=n; + buffer[i++]=HEXCHAR(HIGHNIBBLE(n)); + buffer[i++]=CIN_SYSEX; + buffer[i++]=HEXCHAR(LOWNIBBLE(n)); + + n=rectype; + checksum+=n; + buffer[i++]=HEXCHAR(HIGHNIBBLE(n)); + buffer[i++]=HEXCHAR(LOWNIBBLE(n)); + buffer[i++]=CIN_SYSEX; + thirdone=0; + for (j=0; j +#include +#include +#include +#include "usb_generic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern USBCompositePart usbMIDIPart; + +typedef union { + uint8 byte[4]; + uint32 data; +} USB_MIDI_Event_Packet; + +/* + * USB MIDI Requests + */ + +/* + * Descriptors, etc. + */ +#define USB_DESCRIPTOR_TYPE_CS_INTERFACE 0x24 +#define USB_DESCRIPTOR_TYPE_CS_ENDPOINT 0x25 + + +#define USB_DEVICE_CLASS_UNDEFINED 0x00 +#define USB_DEVICE_CLASS_CDC 0x02 +#define USB_DEVICE_SUBCLASS_UNDEFINED 0x00 + +#define USB_INTERFACE_CLASS_AUDIO 0x01 +#define USB_INTERFACE_SUBCLASS_UNDEFINED 0x00 +#define USB_INTERFACE_AUDIOCONTROL 0x01 +#define USB_INTERFACE_AUDIOSTREAMING 0x02 +#define USB_INTERFACE_MIDISTREAMING 0x03 + +/* MIDI Streaming class specific interfaces */ +#define MIDI_IN_JACK 0x02 +#define MIDI_OUT_JACK 0x03 + +#define MIDI_JACK_EMBEDDED 0x01 +#define MIDI_JACK_EXTERNAL 0x02 + + +#define AC_CS_INTERFACE_DESCRIPTOR_SIZE(DataSize) (8 + DataSize) +#define AC_CS_INTERFACE_DESCRIPTOR(DataSize) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint8 SubType; \ + uint16 bcdADC; \ + uint16 wTotalLength; \ + uint8 bInCollection; \ + uint8 baInterfaceNr[DataSize]; \ + } __packed + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint8 SubType; + uint16 bcdADC; + uint16 wTotalLength; + } __packed MS_CS_INTERFACE_DESCRIPTOR; + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint8 SubType; + uint8 bJackType; + uint8 bJackId; + uint8 iJack; + } __packed MIDI_IN_JACK_DESCRIPTOR; + +#define MIDI_OUT_JACK_DESCRIPTOR_SIZE(DataSize) (7 + 2*DataSize) +#define MIDI_OUT_JACK_DESCRIPTOR(DataSize) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint8 SubType; \ + uint8 bJackType; \ + uint8 bJackId; \ + uint8 bNrInputPins; \ + uint8 baSourceId[DataSize]; \ + uint8 baSourcePin[DataSize]; \ + uint8 iJack; \ + } __packed + + +#define MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(DataSize) (4 + DataSize) +#define MS_CS_BULK_ENDPOINT_DESCRIPTOR(DataSize) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint8 SubType; \ + uint8 bNumEmbMIDIJack; \ + uint8 baAssocJackID[DataSize]; \ + } __packed + +/* + * Endpoint configuration + */ + +#define USB_MIDI_TX_EPSIZE 0x40 + +#define USB_MIDI_RX_EPSIZE 0x40 + +#ifndef __cplusplus +#define USB_MIDI_DECLARE_DEV_DESC(vid, pid) \ + { \ + .bLength = sizeof(usb_descriptor_device), \ + .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, \ + .bcdUSB = 0x0110, \ + .bDeviceClass = USB_DEVICE_CLASS_UNDEFINED, \ + .bDeviceSubClass = USB_DEVICE_SUBCLASS_UNDEFINED, \ + .bDeviceProtocol = 0x00, \ + .bMaxPacketSize0 = 0x40, \ + .idVendor = vid, \ + .idProduct = pid, \ + .bcdDevice = 0x0200, \ + .iManufacturer = 0x01, \ + .iProduct = 0x02, \ + .iSerialNumber = 0x00, \ + .bNumConfigurations = 0x01, \ + } +#endif + +/* + * Sysex Stuff. + */ + +#define SYSEX_BUFFER_LENGTH 256 + + + /* + * MIDI interface + */ + + void usb_midi_putc(char ch); + uint32 usb_midi_tx(const uint32* buf, uint32 len); + uint32 usb_midi_rx(uint32* buf, uint32 len); + uint32 usb_midi_peek(uint32* buf, uint32 len); + + uint32 usb_midi_data_available(void); /* in RX buffer */ + uint16 usb_midi_get_pending(void); + uint8 usb_midi_is_transmitting(void); + + void sendThroughSysex(char *printbuffer, int bufferlength); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_scsi.c b/STM32F1/libraries/USBComposite/usb_scsi.c new file mode 100644 index 0000000..2ff3dfd --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_scsi.c @@ -0,0 +1,333 @@ +#include "usb_mass.h" +#include "usb_mass_mal.h" +#include "usb_mass_internal.h" +#include "usb_scsi.h" + +#include +#include +#include + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" +#include "usb_regs.h" + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +#define SCSI_READ_FORMAT_CAPACITY_DATA_LEN 0x0C +#define SCSI_READ_FORMAT_CAPACITY10_DATA_LEN 0x08 +#define SCSI_MODE_SENSE6_DATA_LEN 0x04 +#define SCSI_MODE_SENSE10_DATA_LEN 0x08 + +#define SCSI_TXFR_IDLE 0 +#define SCSI_TXFR_ONGOING 1 + +extern uint32_t usb_mass_sil_write(uint8_t* pBufferPointer, uint32_t wBufferSize); + +/* See usb_scsi_data.c */ +extern uint8_t SCSI_page00InquiryData[]; +extern uint8_t SCSI_standardInquiryData[]; +extern uint8_t SCSI_standardInquiryData2[]; +extern uint8_t SCSI_senseData[]; +extern uint8_t SCSI_modeSense6Data[]; +extern uint8_t SCSI_modeSense10Data[]; +extern uint8_t SCSI_readFormatCapacityData[]; +extern uint8_t SCSI_readFormatCapacity10Data[]; + +uint32_t SCSI_lba; +uint32_t SCSI_blkLen; +uint8_t SCSI_transferState = SCSI_TXFR_IDLE; +uint32_t SCSI_blockReadCount = 0; +uint32_t SCSI_blockOffset; +uint32_t SCSI_counter = 0; +uint8_t SCSI_dataBuffer[512]; /* 512 bytes (SDCard block size) */ + +uint8_t scsi_address_management(uint8_t lun, uint8_t cmd, uint32_t lba, uint32_t blockNbr); +void scsi_read_memory(uint8_t lun, uint32_t memoryOffset, uint32_t transferLength); +void scsi_write_memory(uint8_t lun, uint32_t memoryOffset, uint32_t transferLength); + +void scsi_inquiry_cmd(uint8_t lun) { + uint8_t* inquiryData; + uint16_t inquiryDataLength; + + if (usb_mass_CBW.CB[1] & 0x01) /*Evpd is set*/ { + inquiryData = SCSI_page00InquiryData; + inquiryDataLength = 5; + } else { + if (lun == 0) { + inquiryData = SCSI_standardInquiryData; + } else { + inquiryData = SCSI_standardInquiryData2; + } + + if (usb_mass_CBW.CB[4] <= SCSI_STANDARD_INQUIRY_DATA_LEN) { + inquiryDataLength = usb_mass_CBW.CB[4]; + } else { + inquiryDataLength = SCSI_STANDARD_INQUIRY_DATA_LEN; + } + } + usb_mass_transfer_data_request(inquiryData, inquiryDataLength); +} + +void scsi_request_sense_cmd(uint8_t lun) { + uint8_t requestSenseDataLength; + if (usb_mass_CBW.CB[4] <= SCSI_REQUEST_SENSE_DATA_LEN) { + requestSenseDataLength = usb_mass_CBW.CB[4]; + } else { + requestSenseDataLength = SCSI_REQUEST_SENSE_DATA_LEN; + } + usb_mass_transfer_data_request(SCSI_senseData, requestSenseDataLength); +} + +void scsi_start_stop_unit_cmd(uint8_t lun) { + usb_mass_bot_set_csw(BOT_CSW_CMD_PASSED, BOT_SEND_CSW_ENABLE); +} + +void scsi_mode_sense6_cmd(uint8_t lun) { + usb_mass_transfer_data_request(SCSI_modeSense6Data, SCSI_MODE_SENSE6_DATA_LEN); +} + +void scsi_mode_sense10_cmd(uint8_t lun) { + usb_mass_transfer_data_request(SCSI_modeSense10Data, SCSI_MODE_SENSE10_DATA_LEN); +} + +void scsi_read_format_capacity_cmd(uint8_t lun) { + if (usb_mass_mal_get_status(lun)) { + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_NOT_READY, SCSI_MEDIUM_NOT_PRESENT); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_ENABLE); + usb_mass_bot_abort(BOT_DIR_IN); + return; + } + SCSI_readFormatCapacityData[4] = (uint8_t) (usb_mass_drives[lun].blockCount >> 24); + SCSI_readFormatCapacityData[5] = (uint8_t) (usb_mass_drives[lun].blockCount >> 16); + SCSI_readFormatCapacityData[6] = (uint8_t) (usb_mass_drives[lun].blockCount >> 8); + SCSI_readFormatCapacityData[7] = (uint8_t) (usb_mass_drives[lun].blockCount); + + SCSI_readFormatCapacityData[9] = (uint8_t) (SCSI_BLOCK_SIZE >> 16); + SCSI_readFormatCapacityData[10] = (uint8_t) (SCSI_BLOCK_SIZE >> 8); + SCSI_readFormatCapacityData[11] = (uint8_t) (SCSI_BLOCK_SIZE); + usb_mass_transfer_data_request(SCSI_readFormatCapacityData, SCSI_READ_FORMAT_CAPACITY_DATA_LEN); +} + +void scsi_read_capacity10_cmd(uint8_t lun) { + if (usb_mass_mal_get_status(lun)) { + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_NOT_READY, SCSI_MEDIUM_NOT_PRESENT); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_ENABLE); + usb_mass_bot_abort(BOT_DIR_IN); + return; + } + + SCSI_readFormatCapacity10Data[0] = (uint8_t) ((usb_mass_drives[lun].blockCount - 1) >> 24); + SCSI_readFormatCapacity10Data[1] = (uint8_t) ((usb_mass_drives[lun].blockCount - 1) >> 16); + SCSI_readFormatCapacity10Data[2] = (uint8_t) ((usb_mass_drives[lun].blockCount - 1) >> 8); + SCSI_readFormatCapacity10Data[3] = (uint8_t) (usb_mass_drives[lun].blockCount - 1); + + SCSI_readFormatCapacity10Data[4] = (uint8_t) (SCSI_BLOCK_SIZE >> 24); + SCSI_readFormatCapacity10Data[5] = (uint8_t) (SCSI_BLOCK_SIZE >> 16); + SCSI_readFormatCapacity10Data[6] = (uint8_t) (SCSI_BLOCK_SIZE >> 8); + SCSI_readFormatCapacity10Data[7] = (uint8_t) (SCSI_BLOCK_SIZE); + usb_mass_transfer_data_request(SCSI_readFormatCapacity10Data, SCSI_READ_FORMAT_CAPACITY10_DATA_LEN); +} + +void scsi_read10_cmd(uint8_t lun, uint32_t lba, uint32_t blockNbr) { + if (usb_mass_botState == BOT_STATE_IDLE) { + if (!(scsi_address_management(usb_mass_CBW.bLUN, SCSI_READ10, lba, blockNbr))) /*address out of range*/ { + return; + } + + if ((usb_mass_CBW.bmFlags & 0x80) != 0) { + usb_mass_botState = BOT_STATE_DATA_IN; + scsi_read_memory(lun, lba, blockNbr); + } else { + usb_mass_bot_abort(BOT_DIR_BOTH); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_ENABLE); + } + return; + } else if (usb_mass_botState == BOT_STATE_DATA_IN) { + scsi_read_memory(lun, lba, blockNbr); + } +} + +void scsi_write10_cmd(uint8_t lun, uint32_t lba, uint32_t blockNbr) { + if (usb_mass_botState == BOT_STATE_IDLE) { + if (!(scsi_address_management(usb_mass_CBW.bLUN, SCSI_WRITE10, lba, blockNbr)))/*address out of range*/ { + return; + } + + if ((usb_mass_CBW.bmFlags & 0x80) == 0) { + usb_mass_botState = BOT_STATE_DATA_OUT; + SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); + } else { + usb_mass_bot_abort(BOT_DIR_IN); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + } + return; + } else if (usb_mass_botState == BOT_STATE_DATA_OUT) { + scsi_write_memory(lun, lba, blockNbr); + } +} + +void scsi_test_unit_ready_cmd(uint8_t lun) { + if (usb_mass_mal_get_status(lun)) { + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_NOT_READY, SCSI_MEDIUM_NOT_PRESENT); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_ENABLE); + usb_mass_bot_abort(BOT_DIR_IN); + return; + } else { + usb_mass_bot_set_csw(BOT_CSW_CMD_PASSED, BOT_SEND_CSW_ENABLE); + } +} + +void scsi_verify10_cmd(uint8_t lun) { + if ((usb_mass_CBW.dDataLength == 0) && !(usb_mass_CBW.CB[1] & SCSI_BLKVFY))/* BLKVFY not set*/ { + usb_mass_bot_set_csw(BOT_CSW_CMD_PASSED, BOT_SEND_CSW_ENABLE); + } else { + usb_mass_bot_abort(BOT_DIR_BOTH); + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + } +} + +void scsi_format_cmd(uint8_t lun) { + if (usb_mass_mal_get_status(lun)) { + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_NOT_READY, SCSI_MEDIUM_NOT_PRESENT); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_ENABLE); + usb_mass_bot_abort(BOT_DIR_IN); + return; + } + usb_mass_mal_format(lun); + usb_mass_bot_set_csw(BOT_CSW_CMD_PASSED, BOT_SEND_CSW_ENABLE); +} + +void scsi_set_sense_data(uint8_t lun, uint8_t sensKey, uint8_t asc) { + SCSI_senseData[2] = sensKey; + SCSI_senseData[12] = asc; +} + +void scsi_invalid_cmd(uint8_t lun) { + if (usb_mass_CBW.dDataLength == 0) { + usb_mass_bot_abort(BOT_DIR_IN); + } else { + if ((usb_mass_CBW.bmFlags & 0x80) != 0) { + usb_mass_bot_abort(BOT_DIR_IN); + } else { + usb_mass_bot_abort(BOT_DIR_BOTH); + } + } + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); +} + +uint8_t scsi_address_management(uint8_t lun, uint8_t cmd, uint32_t lba, uint32_t blockNbr) { + + if ((lba + blockNbr) > usb_mass_drives[lun].blockCount) { + if (cmd == SCSI_WRITE10) { + usb_mass_bot_abort(BOT_DIR_BOTH); + } + usb_mass_bot_abort(BOT_DIR_IN); + scsi_set_sense_data(lun, SCSI_ILLEGAL_REQUEST, SCSI_ADDRESS_OUT_OF_RANGE); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + return (FALSE); + } + + + if (usb_mass_CBW.dDataLength != blockNbr * SCSI_BLOCK_SIZE) { + if (cmd == SCSI_WRITE10) { + usb_mass_bot_abort(BOT_DIR_BOTH); + } else { + usb_mass_bot_abort(BOT_DIR_IN); + } + scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); + usb_mass_bot_set_csw(BOT_CSW_CMD_FAILED, BOT_SEND_CSW_DISABLE); + return (FALSE); + } + return (TRUE); +} + +void scsi_read_memory(uint8_t lun, uint32_t memoryOffset, uint32_t transferLength) { + static uint32_t offset, length; + + if (SCSI_transferState == SCSI_TXFR_IDLE) { + offset = memoryOffset * SCSI_BLOCK_SIZE; + length = transferLength * SCSI_BLOCK_SIZE; + SCSI_transferState = SCSI_TXFR_ONGOING; + } + + if (SCSI_transferState == SCSI_TXFR_ONGOING) { + if (SCSI_blockReadCount == 0) { + usb_mass_mal_read_memory(lun, offset, SCSI_dataBuffer, SCSI_BLOCK_SIZE); + + usb_mass_sil_write(SCSI_dataBuffer, MAX_BULK_PACKET_SIZE); + + SCSI_blockReadCount = SCSI_BLOCK_SIZE - MAX_BULK_PACKET_SIZE; + SCSI_blockOffset = MAX_BULK_PACKET_SIZE; + } else { + usb_mass_sil_write(SCSI_dataBuffer + SCSI_blockOffset, MAX_BULK_PACKET_SIZE); + + SCSI_blockReadCount -= MAX_BULK_PACKET_SIZE; + SCSI_blockOffset += MAX_BULK_PACKET_SIZE; + } + + SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_VAL); + + offset += MAX_BULK_PACKET_SIZE; + length -= MAX_BULK_PACKET_SIZE; + + usb_mass_CSW.dDataResidue -= MAX_BULK_PACKET_SIZE; + usb_mass_CSW.bStatus = BOT_CSW_CMD_PASSED; + // TODO: Led_RW_ON(); + } + + if (length == 0) { + SCSI_blockReadCount = 0; + SCSI_blockOffset = 0; + offset = 0; + usb_mass_botState = BOT_STATE_DATA_IN_LAST; + SCSI_transferState = SCSI_TXFR_IDLE; + // TODO: Led_RW_OFF(); + } +} + +void scsi_write_memory(uint8_t lun, uint32_t memoryOffset, uint32_t transferLength) { + static uint32_t offset, length; + uint32_t idx; + uint32_t temp = SCSI_counter + 64; + + if (SCSI_transferState == SCSI_TXFR_IDLE) { + offset = memoryOffset * SCSI_BLOCK_SIZE; + length = transferLength * SCSI_BLOCK_SIZE; + SCSI_transferState = SCSI_TXFR_ONGOING; + } + + if (SCSI_transferState == SCSI_TXFR_ONGOING) { + + for (idx = 0; SCSI_counter < temp; SCSI_counter++) { + *((uint8_t *) SCSI_dataBuffer + SCSI_counter) = usb_mass_bulkDataBuff[idx++]; + } + + offset += usb_mass_dataLength; + length -= usb_mass_dataLength; + + if (!(length % SCSI_BLOCK_SIZE)) { + SCSI_counter = 0; + usb_mass_mal_write_memory(lun, offset - SCSI_BLOCK_SIZE, SCSI_dataBuffer, SCSI_BLOCK_SIZE); + } + + usb_mass_CSW.dDataResidue -= usb_mass_dataLength; + SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); /* enable the next transaction*/ + + // TODO: Led_RW_ON(); + } + + if ((length == 0) || (usb_mass_botState == BOT_STATE_CSW_Send)) { + SCSI_counter = 0; + usb_mass_bot_set_csw(BOT_CSW_CMD_PASSED, BOT_SEND_CSW_ENABLE); + SCSI_transferState = SCSI_TXFR_IDLE; + // TODO: Led_RW_OFF(); + } +} \ No newline at end of file diff --git a/STM32F1/libraries/USBComposite/usb_scsi.h b/STM32F1/libraries/USBComposite/usb_scsi.h new file mode 100644 index 0000000..a5b121a --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_scsi.h @@ -0,0 +1,96 @@ +#ifndef __USB_SCSI_H +#define __USB_SCSI_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SCSI_BLOCK_SIZE 512 + + /* SCSI Commands */ +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SELECT6 0x15 +#define SCSI_MODE_SELECT10 0x55 +#define SCSI_MODE_SENSE6 0x1A +#define SCSI_MODE_SENSE10 0x5A +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E +#define SCSI_READ6 0x08 +#define SCSI_READ10 0x28 +#define SCSI_READ12 0xA8 +#define SCSI_READ16 0x88 + +#define SCSI_READ_CAPACITY10 0x25 +#define SCSI_READ_CAPACITY16 0x9E + +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_WRITE6 0x0A +#define SCSI_WRITE10 0x2A +#define SCSI_WRITE12 0xAA +#define SCSI_WRITE16 0x8A + +#define SCSI_VERIFY10 0x2F +#define SCSI_VERIFY12 0xAF +#define SCSI_VERIFY16 0x8F + +#define SCSI_SEND_DIAGNOSTIC 0x1D +#define SCSI_READ_FORMAT_CAPACITIES 0x23 + +#define SCSI_NO_SENSE 0 +#define SCSI_RECOVERED_ERROR 1 +#define SCSI_NOT_READY 2 +#define SCSI_MEDIUM_ERROR 3 +#define SCSI_HARDWARE_ERROR 4 +#define SCSI_ILLEGAL_REQUEST 5 +#define SCSI_UNIT_ATTENTION 6 +#define SCSI_DATA_PROTECT 7 +#define SCSI_BLANK_CHECK 8 +#define SCSI_VENDOR_SPECIFIC 9 +#define SCSI_COPY_ABORTED 10 +#define SCSI_ABORTED_COMMAND 11 +#define SCSI_VOLUME_OVERFLOW 13 +#define SCSI_MISCOMPARE 14 + +#define SCSI_INVALID_COMMAND 0x20 +#define SCSI_INVALID_FIELED_IN_COMMAND 0x24 +#define SCSI_PARAMETER_LIST_LENGTH_ERROR 0x1A +#define SCSI_INVALID_FIELD_IN_PARAMETER_LIST 0x26 +#define SCSI_ADDRESS_OUT_OF_RANGE 0x21 +#define SCSI_MEDIUM_NOT_PRESENT 0x3A +#define SCSI_MEDIUM_HAVE_CHANGED 0x28 + +#define SCSI_READ_FORMAT_CAPACITY_DATA_LEN 0x0C +#define SCSI_READ_CAPACITY10_DATA_LEN 0x08 +#define SCSI_MODE_SENSE10_DATA_LEN 0x08 +#define SCSI_MODE_SENSE6_DATA_LEN 0x04 +#define SCSI_REQUEST_SENSE_DATA_LEN 0x12 +#define SCSI_STANDARD_INQUIRY_DATA_LEN 0x24 +#define SCSI_BLKVFY 0x04 + + extern uint32_t SCSI_lba; + extern uint32_t SCSI_blkLen; + + void scsi_inquiry_cmd(uint8_t lun); + void scsi_request_sense_cmd(uint8_t lun); + void scsi_start_stop_unit_cmd(uint8_t lun); + void scsi_mode_sense6_cmd(uint8_t lun); + void scsi_mode_sense10_cmd(uint8_t lun); + void scsi_read_format_capacity_cmd(uint8_t lun); + void scsi_read_capacity10_cmd(uint8_t lun); + void scsi_read10_cmd(uint8_t lun, uint32_t lba, uint32_t blockNbr); + void scsi_write10_cmd(uint8_t lun, uint32_t lba, uint32_t blockNbr); + void scsi_test_unit_ready_cmd(uint8_t lun); + void scsi_verify10_cmd(uint8_t lun); + void scsi_format_cmd(uint8_t lun); + void scsi_set_sense_data(uint8_t lun, uint8_t sensKey, uint8_t asc); + void scsi_invalid_cmd(uint8_t lun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/USBComposite/usb_scsi_data.c b/STM32F1/libraries/USBComposite/usb_scsi_data.c new file mode 100644 index 0000000..a692fd7 --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_scsi_data.c @@ -0,0 +1,120 @@ + +#include "usb_scsi.h" + +uint8_t SCSI_page00InquiryData[] = { + 0x00, /* PERIPHERAL QUALIFIER & PERIPHERAL DEVICE TYPE*/ + 0x00, + 0x00, + 0x00, + 0x00 /* Supported Pages 00*/ +}; + +uint8_t SCSI_standardInquiryData[] = { + 0x00, /* Direct Access Device */ + 0x80, /* RMB = 1: Removable Medium */ + 0x02, /* Version: No conformance claim to standard */ + 0x02, + + 36 - 4, /* Additional Length */ + 0x00, /* SCCS = 1: Storage Controller Component */ + 0x00, + 0x00, + /* Vendor Identification */ + 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', + /* Product Identification */ + 'S', 'D', ' ', 'F', 'l', 'a', 's', 'h', ' ', + 'D', 'i', 's', 'k', ' ', ' ', ' ', + /* Product Revision Level */ + '1', '.', '0', ' ' +}; + +uint8_t SCSI_standardInquiryData2[] = { + 0x00, /* Direct Access Device */ + 0x80, /* RMB = 1: Removable Medium */ + 0x02, /* Version: No conformance claim to standard */ + 0x02, + + 36 - 4, /* Additional Length */ + 0x00, /* SCCS = 1: Storage Controller Component */ + 0x00, + 0x00, + /* Vendor Identification */ + 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', + /* Product Identification */ + 'N', 'A', 'N', 'D', ' ', 'F', 'l', 'a', 's', 'h', ' ', + 'D', 'i', 's', 'k', ' ', + /* Product Revision Level */ + '1', '.', '0', ' ' +}; + +uint8_t SCSI_senseData[] = { + 0x70, /*RespCode*/ + 0x00, /*SegmentNumber*/ + SCSI_NO_SENSE, /* Sens_Key*/ + 0x00, + 0x00, + 0x00, + 0x00, /*Information*/ + 0x0A, /*AdditionalSenseLength*/ + 0x00, + 0x00, + 0x00, + 0x00, /*CmdInformation*/ + SCSI_NO_SENSE, /*Asc*/ + 0x00, /*ASCQ*/ + 0x00, /*FRUC*/ + 0x00, /*TBD*/ + 0x00, + 0x00 /*SenseKeySpecific*/ +}; + +uint8_t SCSI_modeSense6Data[] = { + 0x03, + 0x00, + 0x00, + 0x00, +}; + +uint8_t SCSI_modeSense10Data[] = { + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +uint8_t SCSI_readFormatCapacityData[] = { + 0x00, + 0x00, + 0x00, + 0x08, /* Capacity List Length */ + + /* Block Count */ + 0, + 0, + 0, + 0, + + /* Block Length */ + 0x02, /* Descriptor Code: Formatted Media */ + 0, + 0, + 0 +}; + +uint8_t SCSI_readFormatCapacity10Data[] = { + /* Last Logical Block */ + 0, + 0, + 0, + 0, + + /* Block Length */ + 0, + 0, + 0, + 0 +}; \ No newline at end of file diff --git a/STM32F3/cores/maple/libmaple/dma_private.h b/STM32F1/libraries/USBComposite/usb_setup.cpp similarity index 56% rename from STM32F3/cores/maple/libmaple/dma_private.h rename to STM32F1/libraries/USBComposite/usb_setup.cpp index b25ded2..47fd3db 100644 --- a/STM32F3/cores/maple/libmaple/dma_private.h +++ b/STM32F1/libraries/USBComposite/usb_setup.cpp @@ -1,61 +1,58 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -#ifndef _LIBMAPLE_DMA_PRIVATE_H_ -#define _LIBMAPLE_DMA_PRIVATE_H_ - -#include -#include - -/* - * IRQ handling - */ - -/* Wrap this in an ifdef to shut up GCC. (We provide DMA_GET_HANDLER - * in the series support files, which need dma_irq_handler().) */ -#ifdef DMA_GET_HANDLER -static __always_inline void dma_irq_handler(dma_dev *dev, dma_tube tube) { - void (*handler)(void) = DMA_GET_HANDLER(dev, tube); - if (handler) { - handler(); - dma_clear_isr_bits(dev, tube); /* in case handler doesn't */ - } -} -#endif - -/* - * Conveniences for dealing with tube sources/destinations - */ - -enum dma_atype { - DMA_ATYPE_MEM, - DMA_ATYPE_PER, - DMA_ATYPE_OTHER, -}; - -enum dma_atype _dma_addr_type(__io void *addr); - -#endif +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +/** + * @file wirish/stm32f1/boards_setup.cpp + * @author Marti Bolivar + * @brief STM32F1 chip setup. + * + * This file controls how init() behaves on the STM32F1. Be very + * careful when changing anything here. Many of these values depend + * upon each other. + */ + +#include "boards_private.h" +#include +#include + +#include + +namespace wirish { + namespace priv { + + void board_setup_usb(void) { +#ifdef GENERIC_BOOTLOADER + //Reset the USB interface on generic boards - developed by Victor PV + gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_OUTPUT_PP); + gpio_write_bit(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit,0); + + for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin + gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING); +#endif + } + + } +} diff --git a/STM32F1/libraries/USBComposite/usb_x360.c b/STM32F1/libraries/USBComposite/usb_x360.c new file mode 100644 index 0000000..9c5bfd7 --- /dev/null +++ b/STM32F1/libraries/USBComposite/usb_x360.c @@ -0,0 +1,486 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include "usb_generic.h" +#include "usb_x360.h" + +#include + +#include +#include +#include + +/* Private headers */ +#include "usb_lib_globals.h" +#include "usb_reg_map.h" + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" +#include "usb_def.h" + +typedef enum _HID_REQUESTS +{ + + GET_REPORT = 1, + GET_IDLE, + GET_PROTOCOL, + + SET_REPORT = 9, + SET_IDLE, + SET_PROTOCOL + +} HID_REQUESTS; + +#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) +#define HID_ENDPOINT_INT 1 +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 + +#define HID_DESCRIPTOR_TYPE 0x21 + +#define REPORT_DESCRIPTOR 0x22 + + +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t numDesc; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; +} HIDDescriptor; + +#define X360_INTERFACE_OFFSET 0 +#define X360_INTERFACE_NUMBER (X360_INTERFACE_OFFSET+usbX360Part.startInterface) +#define X360_ENDPOINT_TX 0 +#define X360_ENDPOINT_RX 1 +#define USB_X360_RX_ADDR x360Endpoints[X360_ENDPOINT_RX].pmaAddress +#define USB_X360_TX_ADDR x360Endpoints[X360_ENDPOINT_TX].pmaAddress +#define USB_X360_RX_ENDP x360Endpoints[X360_ENDPOINT_RX].address +#define USB_X360_TX_ENDP x360Endpoints[X360_ENDPOINT_TX].address + +u16 GetEPTxAddr(u8 bEpNum); + +static uint32 ProtocolValue; + +static void x360DataTxCb(void); +static void x360DataRxCb(void); +static void (*x360_rumble_callback)(uint8 left, uint8 right); +static void (*x360_led_callback)(uint8 pattern); + +static void x360Reset(void); +static RESULT x360DataSetup(uint8 request); +static RESULT x360NoDataSetup(uint8 request); +static uint8 *HID_GetProtocolValue(uint16 Length); + +/* + * Descriptors + */ + +#if 0 +const uint8_t hid_report_descriptor[] = { + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x05, // USAGE (Game Pad) + 0xa1, 0x01, // COLLECTION (Application) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x3a, // USAGE (Counted Buffer) + 0xa1, 0x02, // COLLECTION (Logical) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x3f, // USAGE (Reserved) + 0x09, 0x3b, // USAGE (Byte Count) + 0x81, 0x01, // INPUT (Cnst,Ary,Abs) + 0x75, 0x01, // REPORT_SIZE (1) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x45, 0x01, // PHYSICAL_MAXIMUM (1) + 0x95, 0x04, // REPORT_COUNT (4) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x0c, // USAGE_MINIMUM (Button 12) + 0x29, 0x0f, // USAGE_MAXIMUM (Button 15) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x01, // REPORT_SIZE (1) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x45, 0x01, // PHYSICAL_MAXIMUM (1) + 0x95, 0x04, // REPORT_COUNT (4) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x09, 0x09, // USAGE (Button 9) + 0x09, 0x0a, // USAGE (Button 10) + 0x09, 0x07, // USAGE (Button 7) + 0x09, 0x08, // USAGE (Button 8) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x01, // REPORT_SIZE (1) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x45, 0x01, // PHYSICAL_MAXIMUM (1) + 0x95, 0x03, // REPORT_COUNT (3) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x09, 0x05, // USAGE (Button 5) + 0x09, 0x06, // USAGE (Button 6) + 0x09, 0x0b, // USAGE (Button 11) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Cnst,Ary,Abs) + 0x75, 0x01, // REPORT_SIZE (1) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x45, 0x01, // PHYSICAL_MAXIMUM (1) + 0x95, 0x04, // REPORT_COUNT (4) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x04, // USAGE_MAXIMUM (Button 4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x08, // REPORT_SIZE (8) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255) + 0x95, 0x02, // REPORT_COUNT (2) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x10, // REPORT_SIZE (16) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) + 0x36, 0x00, 0x80, // PHYSICAL_MINIMUM (-32768) + 0x46, 0xff, 0x7f, // PHYSICAL_MAXIMUM (32767) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + 0x95, 0x02, // REPORT_COUNT (2) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + 0x95, 0x02, // REPORT_COUNT (2) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION + 0xc0 // END_COLLECTION +}; +#endif + +typedef struct { +// usb_descriptor_config_header Config_Header; + usb_descriptor_interface HID_Interface; + uint8 unknown_descriptor1[17]; + usb_descriptor_endpoint DataInEndpoint; + usb_descriptor_endpoint DataOutEndpoint; +} __packed usb_descriptor_config; + + +#define MAX_POWER (100 >> 1) +static const usb_descriptor_config X360Descriptor_Config = +{ +#if 0 + .Config_Header = { + .bLength = sizeof(usb_descriptor_config_header), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = sizeof(usb_descriptor_config),//0, + .bNumInterfaces = 0x01, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED), + .bMaxPower = MAX_POWER, + }, +#endif + + .HID_Interface = { + .bLength = sizeof(usb_descriptor_interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = X360_INTERFACE_OFFSET, // PATCH + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = 0xFF, + .bInterfaceSubClass = 0x5D, + .bInterfaceProtocol = 0x01, + .iInterface = 0x00, + }, + + .unknown_descriptor1 = { + 17,33,0,1,1,37,129,20,0,0,0,0,19,2,8,0,0, + }, + + .DataInEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | X360_ENDPOINT_TX),//PATCH + .bmAttributes = USB_EP_TYPE_INTERRUPT, + .wMaxPacketSize = 0x20, + .bInterval = 4, + }, + + .DataOutEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | X360_ENDPOINT_RX),//PATCH + .bmAttributes = USB_EP_TYPE_INTERRUPT, + .wMaxPacketSize = 0x20, + .bInterval = 8, + }, +}; + +static USBEndpointInfo x360Endpoints[2] = { + { + .callback = x360DataTxCb, + .bufferSize = 0x20, + .type = USB_EP_EP_TYPE_INTERRUPT, + .tx = 1 + }, + { + .callback = x360DataRxCb, + .bufferSize = 0x20, + .type = USB_EP_EP_TYPE_INTERRUPT, + .tx = 0, + } +}; + +#define OUT_BYTE(s,v) out[(uint8*)&(s.v)-(uint8*)&s] + +static void getX360PartDescriptor(uint8* out) { + memcpy(out, &X360Descriptor_Config, sizeof(X360Descriptor_Config)); + // patch to reflect where the part goes in the descriptor + OUT_BYTE(X360Descriptor_Config, HID_Interface.bInterfaceNumber) += usbX360Part.startInterface; + OUT_BYTE(X360Descriptor_Config, DataOutEndpoint.bEndpointAddress) += usbX360Part.startEndpoint; + OUT_BYTE(X360Descriptor_Config, DataInEndpoint.bEndpointAddress) += usbX360Part.startEndpoint; +} + +USBCompositePart usbX360Part = { + .numInterfaces = 1, + .numEndpoints = sizeof(x360Endpoints)/sizeof(*x360Endpoints), + .descriptorSize = sizeof(X360Descriptor_Config), + .getPartDescriptor = getX360PartDescriptor, + .usbInit = NULL, + .usbReset = x360Reset, + .usbDataSetup = x360DataSetup, + .usbNoDataSetup = x360NoDataSetup, + .endpoints = x360Endpoints +}; + + +/* + * Etc. + */ + +/* I/O state */ + +/* Received data */ +static volatile uint8 hidBufferRx[USB_X360_RX_EPSIZE]; + + +/* Number of bytes left to transmit */ +static volatile uint32 n_unsent_bytes = 0; +/* Are we currently sending an IN packet? */ +static volatile uint8 transmitting = 0; + + +/* + * HID interface + */ + +void x360_set_rumble_callback(void (*callback)(uint8 left, uint8 right)) { + x360_rumble_callback = callback; +} + +void x360_set_led_callback(void (*callback)(uint8 pattern)) { + x360_led_callback = callback; +} + +/*void x360_disable(void) { + x360_set_rumble_callback(NULL); + x360_set_led_callback(NULL); + usb_generic_disable(); +}*/ + +void x360_putc(char ch) { + while (!x360_tx((uint8*)&ch, 1)) + ; +} + + +/* This function is non-blocking. + * + * It copies data from a usercode buffer into the USB peripheral TX + * buffer, and returns the number of bytes copied. */ +uint32 x360_tx(const uint8* buf, uint32 len) { + /* Last transmission hasn't finished, so abort. */ + if (x360_is_transmitting()) { + return 0; + } + + /* We can only put USB_X360_TX_EPSIZE bytes in the buffer. */ + if (len > USB_X360_TX_EPSIZE) { + len = USB_X360_TX_EPSIZE; + } + + /* Queue bytes for sending. */ + if (len) { + usb_copy_to_pma(buf, len, GetEPTxAddr(USB_X360_TX_ENDP));//USB_X360_TX_ADDR); + } + // We still need to wait for the interrupt, even if we're sending + // zero bytes. (Sending zero-size packets is useful for flushing + // host-side buffers.) + usb_set_ep_tx_count(USB_X360_TX_ENDP, len); + n_unsent_bytes = len; + transmitting = 1; + usb_set_ep_tx_stat(USB_X360_TX_ENDP, USB_EP_STAT_TX_VALID); + + return len; +} + +uint8 x360_is_transmitting(void) { + return transmitting; +} + +uint16 x360_get_pending(void) { + return n_unsent_bytes; +} + +static void x360DataRxCb(void) +{ + uint32 ep_rx_size = usb_get_ep_rx_count(USB_X360_RX_ENDP); + // This copy won't overwrite unread bytes as long as there is + // enough room in the USB Rx buffer for next packet + uint32 *src = usb_pma_ptr(USB_X360_RX_ADDR); + uint16 tmp = 0; + uint8 val; + uint32 i; + for (i = 0; i < ep_rx_size; i++) { + if (i&1) { + val = tmp>>8; + } else { + tmp = *src++; + val = tmp&0xFF; + } + hidBufferRx[i] = val; + } + + if (ep_rx_size == 3) { + if (x360_led_callback != NULL && hidBufferRx[0] == 1 && hidBufferRx[1] == 3) + x360_led_callback(hidBufferRx[2]); + } + else if (ep_rx_size == 8) { + if (x360_rumble_callback != NULL && hidBufferRx[0] == 0 && hidBufferRx[1] == 8) + x360_rumble_callback(hidBufferRx[3],hidBufferRx[4]); + } + usb_set_ep_rx_stat(USB_X360_RX_ENDP, USB_EP_STAT_RX_VALID); +} + +/* + * Callbacks + */ + +static void x360DataTxCb(void) { + n_unsent_bytes = 0; + transmitting = 0; +} + +static RESULT x360DataSetup(uint8 request) { + uint8* (*CopyRoutine)(uint16) = 0; + +#if 0 + if (request == GET_DESCRIPTOR + && pInformation->USBwIndex0 == X360_INTERFACE_NUMBER && + && (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + && (pInformation->USBwIndex0 == 0)){ + if (pInformation->USBwValue1 == REPORT_DESCRIPTOR){ + CopyRoutine = HID_GetReportDescriptor; + } else + if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE){ + CopyRoutine = HID_GetHIDDescriptor; + } + + } /* End of GET_DESCRIPTOR */ + /*** GET_PROTOCOL ***/ + else +#endif + if(pInformation->USBwIndex0 == X360_INTERFACE_NUMBER && + (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + && request == GET_PROTOCOL){ + CopyRoutine = HID_GetProtocolValue; + } + + if (CopyRoutine == NULL){ + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +} + +static RESULT x360NoDataSetup(uint8 request) { + if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + && (request == SET_PROTOCOL)){ + uint8 wValue0 = pInformation->USBwValue0; + ProtocolValue = wValue0; + return USB_SUCCESS; + }else{ + return USB_UNSUPPORT; + } +} + +static uint8* HID_GetProtocolValue(uint16 Length){ + if (Length == 0){ + pInformation->Ctrl_Info.Usb_wLength = 1; + return NULL; + } else { + return (uint8 *)(&ProtocolValue); + } +} + +static void x360Reset(void) { + /* Reset the RX/TX state */ + n_unsent_bytes = 0; + transmitting = 0; +} \ No newline at end of file diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib_globals.h b/STM32F1/libraries/USBComposite/usb_x360.h similarity index 59% rename from STM32F3/cores/maple/libmaple/usb/usb_lib_globals.h rename to STM32F1/libraries/USBComposite/usb_x360.h index 1cd2754..7d2d3e1 100644 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib_globals.h +++ b/STM32F1/libraries/USBComposite/usb_x360.h @@ -24,29 +24,49 @@ * SOFTWARE. *****************************************************************************/ -#ifndef _USB_LIB_GLOBALS_H_ -#define _USB_LIB_GLOBALS_H_ +#ifndef _USB_X360_H +#define _USB_X360_H -/* usb_lib headers */ -#include "usb_type.h" -#include "usb_core.h" +#include +#include +#include #ifdef __cplusplus extern "C" { #endif -extern USER_STANDARD_REQUESTS User_Standard_Requests; -extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; -extern DEVICE_PROP Device_Property; -extern DEVICE_PROP *pProperty; +/* + * Descriptors, etc. + */ + +//extern const uint8_t hid_report_descriptor[]; -extern DEVICE_INFO Device_Info; -extern DEVICE_INFO *pInformation; +/* + * Endpoint configuration + */ -extern DEVICE Device_Table; -extern u16 SaveRState; -extern u16 SaveTState; +#define USB_X360_TX_EPSIZE 0x20 +#define USB_X360_RX_EPSIZE 0x20 + +/* + * HID interface + */ + +extern USBCompositePart usbX360Part; +void x360_enable(); +void x360_disable(); + +void x360_putc(char ch); +uint32 x360_tx(const uint8* buf, uint32 len); +uint32 x360_rx(uint8* buf, uint32 len); +uint32 x360_hid_peek(uint8* buf, uint32 len); +uint32 x360_data_available(void); /* in RX buffer */ +uint16 x360_get_pending(void); +uint8 x360_is_transmitting(void); +void x360_set_rx_callback(void (*callback)(const uint8* buffer, uint32 size)); +void x360_set_rumble_callback(void (*callback)(uint8 left, uint8 right)); +void x360_set_led_callback(void (*callback)(uint8 pattern)); #ifdef __cplusplus } diff --git a/STM32F1/libraries/WS2812B/README.md b/STM32F1/libraries/WS2812B/README.md new file mode 100644 index 0000000..3f10144 --- /dev/null +++ b/STM32F1/libraries/WS2812B/README.md @@ -0,0 +1,78 @@ +# WS2812B_STM32_Libmaple +WS2812B (Neopixel) library for Arduino STM32 (Libmaple core) + +Written by Roger Clark www.rogerclark.net, from first principals + +This library uses SPI DMA to control a strip of WS2812B (NeoPixel) LEDS + +It should be generally compatible with the Adafruit NeoPixel library, +except I have not had chance to implement one or two of the lesser used functions + +Connect Data In of the strip to SPI1 MOSI + +This library has only been tested on the WS2812B LED. It may not work with the older WS2812 or +other types of addressable RGB LED, becuase it relies on a division multiple of the 72Mhz clock +frequence on the STM32 SPI to generate the correct width T0H pulse, of 400ns +/- 150nS +SPI DIV32 gives a pulse width of 444nS which is well within spec for the WS2812B but +is probably too long for the WS2812 which needs a 350ns pulse for T0H + +##Technical details + +The library uses SPI to send the mark/space encoded data to the LED's + +Each mark/space squarewave is generated by 3 bits of data +A pixel 0 value is achieved by sending the bit pattern 100 +A pixel 1 value is achieved by sending the bit pattern 110 + +Where the duration of each bit is 444nS +Hence 100 generates a mark space value of 444/888nS +and 110 generates a mark space value of 888/444nS + +This method results in the smallest storage requirement and the fastest send times, +however because the 8 bit pixel channel data is encoded in 24 bits, (3 bytes) the values required in each of the 3 bytes to represent +a specific value is not easy to generate. + +The bit pattern in the 3 bytes is +88877766 65554443 33222111 + +For speed of operation the values reqired for each byte for each of the 256 possible values is held in 3 separate 256 byte LUTS +which were pre-computed by this function (which generates the full 24 bit pattern for a given input value (0-255) + +``` +uint32_t convert(uint8_t data) +{ + uint32_t out=0; + for(uint8_t mask = 0x80; mask; mask >>= 1) + { + out=out<<3; + if (data & mask) + { + out = out | 0B110;//Bit high + } + else + { + out = out | 0B100;// bit low + } + } + return out; +} +``` + +The STM32F103 has plenty of flash space (either 64 or 128k), so I used 256 byte LUTs even though the number of unique values in each LUT is +only 8,4 and 8 bytes respectively. +However to use small LUTS requires shifting and masking of the input data, and the code was written with a preference for speed over binary size + +The encoded pixel buffer is 2 bytes longer than the actual encoded data. +The first and last encoded bytes are all zeros. This is because the SPI hardware seems to preload MOSI with its output value before the start +of the DMA transfer, which causes the first encoded pulse to be around 50ns longer than the subsequent bits, (around 490 or 500ns) +This had the effect of causing the first LED to always think the MS bit of the green channel was set to High. + +So having the first encoded byte of zeros, is a work-around , as although the first encoded bit is still 490nS wide its a logic zero and is therefore +not visible, becuase the default state is of the SPI when not transmitting data is logic zero +The last byte was also set to all zeros, as occasionally MOSI seemed to be left set to logic high on completion of the SPI DMA send + +Adding these 2 bytes does slightly slow down the transfer, as it add 444ns * 8 = just over 3.5uS to both end. +But the WS2812B theoretically requires a reset time of more than 50uS between transmissions, so 3.5uS can be part of that time. +In reality the WS2812B seems to only need around 6uS of reset time, so for all practical purposes, there no delays are needed at all in the +library to enforce the reset time, as the overead of the function call and the SPI DMA setup plus the 3.5uS gives the enough reset time. + diff --git a/STM32F1/libraries/WS2812B/examples/WS2812B_test/WS2812B_test.ino b/STM32F1/libraries/WS2812B/examples/WS2812B_test/WS2812B_test.ino new file mode 100644 index 0000000..bf4934f --- /dev/null +++ b/STM32F1/libraries/WS2812B/examples/WS2812B_test/WS2812B_test.ino @@ -0,0 +1,303 @@ +#include + +#define NUM_LEDS 30 +/* + * Note. Library uses SPI1 + * Connect the WS2812B data input to MOSI on your board. + * + */ +WS2812B strip = WS2812B(NUM_LEDS); +// Note. Gamma is not really supported in the library, its only included as some functions used in this example require Gamma +uint8_t LEDGamma[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, + 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, + 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, + 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, + 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, + 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, + 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, +215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 }; + +void setup() +{ + strip.begin();// Sets up the SPI + strip.show();// Clears the strip, as by default the strip data is set to all LED's off. + // strip.setBrightness(8); +} + +void loop() +{ + colorWipe(strip.Color(0, 255, 0), 20); // Green + colorWipe(strip.Color(255, 0, 0), 20); // Red + colorWipe(strip.Color(0, 0, 255), 20); // Blue + rainbow(10); + rainbowCycle(10); + theaterChase(strip.Color(255, 0, 0), 20); // Red + theaterChase(strip.Color(0, 255, 0), 20); // Green + theaterChase(strip.Color(0, 0, 255), 20); // Blue + theaterChaseRainbow(10); + whiteOverRainbow(20,75,5); + pulseWhite(5); + delay(250); + fullWhite(); + delay(250); + rainbowFade2White(3,3,1); +} + +// Fill the dots one after the other with a color +void colorWipe(uint32_t c, uint8_t wait) +{ + for(uint16_t i=0; i= 0 ; j--){ + for(uint16_t i=0; i 255 - fadeMax ){ + fadeVal--; + } + + strip.show(); + delay(wait); + } + + } + + + + delay(500); + + + for(int k = 0 ; k < whiteLoops ; k ++){ + + for(int j = 0; j < 256 ; j++){ + + for(uint16_t i=0; i < strip.numPixels(); i++) { + strip.setPixelColor(i, strip.Color(0,0,0, LEDGamma[j] ) ); + } + strip.show(); + } + + delay(2000); + for(int j = 255; j >= 0 ; j--){ + + for(uint16_t i=0; i < strip.numPixels(); i++) { + strip.setPixelColor(i, strip.Color(0,0,0, LEDGamma[j] ) ); + } + strip.show(); + } + } + + delay(500); + + +} + +void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) { + + if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1; + + int head = whiteLength - 1; + int tail = 0; + + int loops = 3; + int loopNum = 0; + + static unsigned long lastTime = 0; + + + while(true){ + for(int j=0; j<256; j++) { + for(uint16_t i=0; i= tail && i <= head) || (tail > head && i >= tail) || (tail > head && i <= head) ){ + strip.setPixelColor(i, strip.Color(0,0,0, 255 ) ); + } + else{ + strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); + } + + } + + if(millis() - lastTime > whiteSpeed) { + head++; + tail++; + if(head == strip.numPixels()){ + loopNum++; + } + lastTime = millis(); + } + + if(loopNum == loops) return; + + head%=strip.numPixels(); + tail%=strip.numPixels(); + strip.show(); + delay(wait); + } + } + +} +void fullWhite() { + + for(uint16_t i=0; i> 16); +} +uint8_t green(uint32_t c) { + return (c >> 8); +} +uint8_t blue(uint32_t c) { + return (c); +} diff --git a/STM32F1/libraries/WS2812B/keywords.txt b/STM32F1/libraries/WS2812B/keywords.txt new file mode 100644 index 0000000..2d8b83a --- /dev/null +++ b/STM32F1/libraries/WS2812B/keywords.txt @@ -0,0 +1,27 @@ +####################################### +# Syntax Coloring Map For WS2812B +# Class +####################################### + +WS2812B KEYWORD1 + +####################################### +# Methods and Functions +####################################### + +setPixelColor KEYWORD2 +numPixels KEYWORD2 +Color KEYWORD2 +show KEYWORD2 + +clear KEYWORD2 +updateLength KEYWORD2 + +canShow KEYWORD2 + + +####################################### +# Constants +####################################### + + diff --git a/STM32F1/libraries/WS2812B/library.properties b/STM32F1/libraries/WS2812B/library.properties new file mode 100644 index 0000000..936976d --- /dev/null +++ b/STM32F1/libraries/WS2812B/library.properties @@ -0,0 +1,10 @@ +name=WS2812B +version=1.0 +author=Roger Clark, based on the Adafruit Neopixel library API +email= +sentence=WS2812B (Neopixel) library +paragraph=WS2812B (Neopixel) library for STM32F1 LibMaple +url= +architectures=STM32F1 +maintainer=Roger Clark +category=Uncategorized \ No newline at end of file diff --git a/STM32F1/libraries/WS2812B/src/WS2812B.cpp b/STM32F1/libraries/WS2812B/src/WS2812B.cpp new file mode 100644 index 0000000..36483fc --- /dev/null +++ b/STM32F1/libraries/WS2812B/src/WS2812B.cpp @@ -0,0 +1,238 @@ +/*----------------------------------------------------------------------------------------------- + Arduino library to control WS2812B RGB Led strips using the Arduino STM32 LibMaple core + ----------------------------------------------------------------------------------------------- + + Note. + This library has only been tested on the WS2812B LED. It may not work with the older WS2812 or + other types of addressable RGB LED, becuase it relies on a division multiple of the 72Mhz clock + frequence on the STM32 SPI to generate the correct width T0H pulse, of 400ns +/- 150nS + SPI DIV32 gives a pulse width of 444nS which is well within spec for the WS2812B but + is probably too long for the WS2812 which needs a 350ns pulse for T0H + + This WS2811B library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + It 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 Lesser General Public License for more details. + + See . + -----------------------------------------------------------------------------------------------*/ + +#include "WS2812B.h" +#include "pins_arduino.h" +#include "wiring_private.h" +#include + + +// Constructor when n is the number of LEDs in the strip +WS2812B::WS2812B(uint16_t number_of_leds) : + brightness(0), pixels(NULL) +{ + updateLength(number_of_leds); +} + + +WS2812B::~WS2812B() +{ + if(pixels) + { + free(pixels); + } + SPI.end(); +} + +void WS2812B::begin(void) { + +if (!begun) +{ + SPI.setClockDivider(SPI_CLOCK_DIV32);// need bit rate of 400nS but closest we can do @ 72Mhz is 444ns (which is within spec) + SPI.begin(); + begun = true; +} +} + +void WS2812B::updateLength(uint16_t n) +{ + if(doubleBuffer) + { + free(doubleBuffer); + } + + numBytes = (n<<3) + n + 2; // 9 encoded bytes per pixel. 1 byte empty peamble to fix issue with SPI MOSI and on byte at the end to clear down MOSI + // Note. (n<<3) +n is a fast way of doing n*9 + if((doubleBuffer = (uint8_t *)malloc(numBytes*2))) + { + numLEDs = n; + pixels = doubleBuffer; + // Only need to init the part of the double buffer which will be interacted with by the API e.g. setPixelColor + *pixels=0;//clear the preamble byte + *(pixels+numBytes-1)=0;// clear the post send cleardown byte. + clear();// Set the encoded data to all encoded zeros + } + else + { + numLEDs = numBytes = 0; + } +} + +// Sends the current buffer to the leds +void WS2812B::show(void) +{ + SPI.dmaSendAsync(pixels,numBytes);// Start the DMA transfer of the current pixel buffer to the LEDs and return immediately. + + // Need to copy the last / current buffer to the other half of the double buffer as most API code does not rebuild the entire contents + // from scratch. Often just a few pixels are changed e.g in a chaser effect + + if (pixels==doubleBuffer) + { + // pixels was using the first buffer + pixels = doubleBuffer+numBytes; // set pixels to second buffer + memcpy(pixels,doubleBuffer,numBytes);// copy first buffer to second buffer + } + else + { + // pixels was using the second buffer + pixels = doubleBuffer; // set pixels to first buffer + memcpy(pixels,doubleBuffer+numBytes,numBytes); // copy second buffer to first buffer + } +} + +/*Sets a specific pixel to a specific r,g,b colour +* Because the pixels buffer contains the encoded bitstream, which is in triplets +* the lookup table need to be used to find the correct pattern for each byte in the 3 byte sequence. +*/ +void WS2812B::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) + { + uint8_t *bptr = pixels + (n<<3) + n +1; + uint8_t *tPtr = (uint8_t *)encoderLookup + g*2 + g;// need to index 3 x g into the lookup + + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + + tPtr = (uint8_t *)encoderLookup + r*2 + r; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + + tPtr = (uint8_t *)encoderLookup + b*2 + b; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + } + +void WS2812B::setPixelColor(uint16_t n, uint32_t c) + { + uint8_t r,g,b; + + if(brightness) + { + r = ((int)((uint8_t)(c >> 16)) * (int)brightness) >> 8; + g = ((int)((uint8_t)(c >> 8)) * (int)brightness) >> 8; + b = ((int)((uint8_t)c) * (int)brightness) >> 8; + } + else + { + r = (uint8_t)(c >> 16), + g = (uint8_t)(c >> 8), + b = (uint8_t)c; + } + + uint8_t *bptr = pixels + (n<<3) + n +1; + uint8_t *tPtr = (uint8_t *)encoderLookup + g*2 + g;// need to index 3 x g into the lookup + + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + + tPtr = (uint8_t *)encoderLookup + r*2 + r; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + + tPtr = (uint8_t *)encoderLookup + b*2 + b; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; +} + +// Convert separate R,G,B into packed 32-bit RGB color. +// Packed format is always RGB, regardless of LED strand color order. +uint32_t WS2812B::Color(uint8_t r, uint8_t g, uint8_t b) { + return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; +} + +// Convert separate R,G,B,W into packed 32-bit WRGB color. +// Packed format is always WRGB, regardless of LED strand color order. +uint32_t WS2812B::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; +} + + +uint16_t WS2812B::numPixels(void) const { + return numLEDs; +} + +// Adjust output brightness; 0=darkest (off), 255=brightest. This does +// NOT immediately affect what's currently displayed on the LEDs. The +// next call to show() will refresh the LEDs at this level. However, +// this process is potentially "lossy," especially when increasing +// brightness. The tight timing in the WS2811/WS2812 code means there +// aren't enough free cycles to perform this scaling on the fly as data +// is issued. So we make a pass through the existing color data in RAM +// and scale it (subsequent graphics commands also work at this +// brightness level). If there's a significant step up in brightness, +// the limited number of steps (quantization) in the old data will be +// quite visible in the re-scaled version. For a non-destructive +// change, you'll need to re-render the full strip data. C'est la vie. +void WS2812B::setBrightness(uint8_t b) { + // Stored brightness value is different than what's passed. + // This simplifies the actual scaling math later, allowing a fast + // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t, + // adding 1 here may (intentionally) roll over...so 0 = max brightness + // (color values are interpreted literally; no scaling), 1 = min + // brightness (off), 255 = just below max brightness. + uint8_t newBrightness = b + 1; + if(newBrightness != brightness) { // Compare against prior value + // Brightness has changed -- re-scale existing data in RAM + uint8_t c, + *ptr = pixels, + oldBrightness = brightness - 1; // De-wrap old brightness value + uint16_t scale; + if(oldBrightness == 0) scale = 0; // Avoid /0 + else if(b == 255) scale = 65535 / oldBrightness; + else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; + for(uint16_t i=0; i> 8; + } + brightness = newBrightness; + } +} + +//Return the brightness value +uint8_t WS2812B::getBrightness(void) const { + return brightness - 1; +} + +/* +* Sets the encoded pixel data to turn all the LEDs off. +*/ +void WS2812B::clear() +{ + uint8_t * bptr= pixels+1;// Note first byte in the buffer is a preable and is always zero. hence the +1 + uint8_t *tPtr; + + for(int i=0;i< (numLEDs *3);i++) + { + tPtr = (uint8_t *)encoderLookup; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + *bptr++ = *tPtr++; + } +} diff --git a/STM32F1/libraries/WS2812B/src/WS2812B.h b/STM32F1/libraries/WS2812B/src/WS2812B.h new file mode 100644 index 0000000..3a6bcb6 --- /dev/null +++ b/STM32F1/libraries/WS2812B/src/WS2812B.h @@ -0,0 +1,81 @@ +/*-------------------------------------------------------------------- + The WS2812B library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + It 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 Lesser General Public License for more details. + + See . + --------------------------------------------------------------------*/ + +#ifndef WS2812B_H +#define WS2812B_H + +#include +/* + * old version used 3 separate tables, one per byte of the 24 bit encoded data + * +static const uint8_t byte0Lookup[256]={0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD2,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB,0xDB}; +static const uint8_t byte1Lookup[256]={0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D,0x6D}; +static const uint8_t byte2Lookup[256]={0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6,0x24,0x26,0x34,0x36,0xA4,0xA6,0xB4,0xB6}; +*/ + +// New version uses one large LUT as its faster index into sequential bytes for the GRB pattern +static uint8_t encoderLookup[256*3]={ 0x92,0x49,0x24,0x92,0x49,0x26,0x92,0x49,0x34,0x92,0x49,0x36,0x92,0x49,0xA4,0x92,0x49,0xA6,0x92,0x49,0xB4,0x92,0x49,0xB6,0x92,0x4D,0x24,0x92,0x4D,0x26,0x92,0x4D,0x34,0x92,0x4D,0x36,0x92,0x4D,0xA4,0x92,0x4D,0xA6,0x92,0x4D,0xB4,0x92,0x4D,0xB6,0x92,0x69,0x24,0x92,0x69,0x26,0x92,0x69,0x34,0x92,0x69,0x36,0x92,0x69,0xA4,0x92,0x69,0xA6,0x92,0x69,0xB4,0x92,0x69,0xB6,0x92,0x6D,0x24,0x92,0x6D,0x26,0x92,0x6D,0x34,0x92,0x6D,0x36,0x92,0x6D,0xA4,0x92,0x6D,0xA6,0x92,0x6D,0xB4,0x92,0x6D,0xB6,0x93,0x49,0x24,0x93,0x49,0x26,0x93,0x49,0x34,0x93,0x49,0x36,0x93,0x49,0xA4,0x93,0x49,0xA6,0x93,0x49,0xB4,0x93,0x49,0xB6,0x93,0x4D,0x24,0x93,0x4D,0x26,0x93,0x4D,0x34,0x93,0x4D,0x36,0x93,0x4D,0xA4,0x93,0x4D,0xA6,0x93,0x4D,0xB4,0x93,0x4D,0xB6,0x93,0x69,0x24,0x93,0x69,0x26,0x93,0x69,0x34,0x93,0x69,0x36,0x93,0x69,0xA4,0x93,0x69,0xA6,0x93,0x69,0xB4,0x93,0x69,0xB6,0x93,0x6D,0x24,0x93,0x6D,0x26,0x93,0x6D,0x34,0x93,0x6D,0x36,0x93,0x6D,0xA4,0x93,0x6D,0xA6,0x93,0x6D,0xB4,0x93,0x6D,0xB6,0x9A,0x49,0x24,0x9A,0x49,0x26,0x9A,0x49,0x34,0x9A,0x49,0x36,0x9A,0x49,0xA4,0x9A,0x49,0xA6,0x9A,0x49,0xB4,0x9A,0x49,0xB6,0x9A,0x4D,0x24,0x9A,0x4D,0x26,0x9A,0x4D,0x34,0x9A,0x4D,0x36,0x9A,0x4D,0xA4,0x9A,0x4D,0xA6,0x9A,0x4D,0xB4,0x9A,0x4D,0xB6,0x9A,0x69,0x24,0x9A,0x69,0x26,0x9A,0x69,0x34,0x9A,0x69,0x36,0x9A,0x69,0xA4,0x9A,0x69,\ + 0xA6,0x9A,0x69,0xB4,0x9A,0x69,0xB6,0x9A,0x6D,0x24,0x9A,0x6D,0x26,0x9A,0x6D,0x34,0x9A,0x6D,0x36,0x9A,0x6D,0xA4,0x9A,0x6D,0xA6,0x9A,0x6D,0xB4,0x9A,0x6D,0xB6,0x9B,0x49,0x24,0x9B,0x49,0x26,0x9B,0x49,0x34,0x9B,0x49,0x36,0x9B,0x49,0xA4,0x9B,0x49,0xA6,0x9B,0x49,0xB4,0x9B,0x49,0xB6,0x9B,0x4D,0x24,0x9B,0x4D,0x26,0x9B,0x4D,0x34,0x9B,0x4D,0x36,0x9B,0x4D,0xA4,0x9B,0x4D,0xA6,0x9B,0x4D,0xB4,0x9B,0x4D,0xB6,0x9B,0x69,0x24,0x9B,0x69,0x26,0x9B,0x69,0x34,0x9B,0x69,0x36,0x9B,0x69,0xA4,0x9B,0x69,0xA6,0x9B,0x69,0xB4,0x9B,0x69,0xB6,0x9B,0x6D,0x24,0x9B,0x6D,0x26,0x9B,0x6D,0x34,0x9B,0x6D,0x36,0x9B,0x6D,0xA4,0x9B,0x6D,0xA6,0x9B,0x6D,0xB4,0x9B,0x6D,0xB6,0xD2,0x49,0x24,0xD2,0x49,0x26,0xD2,0x49,0x34,0xD2,0x49,0x36,0xD2,0x49,0xA4,0xD2,0x49,0xA6,0xD2,0x49,0xB4,0xD2,0x49,0xB6,0xD2,0x4D,0x24,0xD2,0x4D,0x26,0xD2,0x4D,0x34,0xD2,0x4D,0x36,0xD2,0x4D,0xA4,0xD2,0x4D,0xA6,0xD2,0x4D,0xB4,0xD2,0x4D,0xB6,0xD2,0x69,0x24,0xD2,0x69,0x26,0xD2,0x69,0x34,0xD2,0x69,0x36,0xD2,0x69,0xA4,0xD2,0x69,0xA6,0xD2,0x69,0xB4,0xD2,0x69,0xB6,0xD2,0x6D,0x24,0xD2,0x6D,0x26,0xD2,0x6D,0x34,0xD2,0x6D,0x36,0xD2,0x6D,0xA4,0xD2,0x6D,0xA6,0xD2,0x6D,0xB4,0xD2,0x6D,0xB6,0xD3,0x49,0x24,0xD3,0x49,0x26,0xD3,0x49,0x34,0xD3,0x49,0x36,0xD3,0x49,0xA4,0xD3,0x49,0xA6,0xD3,0x49,0xB4,0xD3,0x49,0xB6,0xD3,0x4D,0x24,0xD3,0x4D,0x26,0xD3,0x4D,0x34,0xD3,\ + 0x4D,0x36,0xD3,0x4D,0xA4,0xD3,0x4D,0xA6,0xD3,0x4D,0xB4,0xD3,0x4D,0xB6,0xD3,0x69,0x24,0xD3,0x69,0x26,0xD3,0x69,0x34,0xD3,0x69,0x36,0xD3,0x69,0xA4,0xD3,0x69,0xA6,0xD3,0x69,0xB4,0xD3,0x69,0xB6,0xD3,0x6D,0x24,0xD3,0x6D,0x26,0xD3,0x6D,0x34,0xD3,0x6D,0x36,0xD3,0x6D,0xA4,0xD3,0x6D,0xA6,0xD3,0x6D,0xB4,0xD3,0x6D,0xB6,0xDA,0x49,0x24,0xDA,0x49,0x26,0xDA,0x49,0x34,0xDA,0x49,0x36,0xDA,0x49,0xA4,0xDA,0x49,0xA6,0xDA,0x49,0xB4,0xDA,0x49,0xB6,0xDA,0x4D,0x24,0xDA,0x4D,0x26,0xDA,0x4D,0x34,0xDA,0x4D,0x36,0xDA,0x4D,0xA4,0xDA,0x4D,0xA6,0xDA,0x4D,0xB4,0xDA,0x4D,0xB6,0xDA,0x69,0x24,0xDA,0x69,0x26,0xDA,0x69,0x34,0xDA,0x69,0x36,0xDA,0x69,0xA4,0xDA,0x69,0xA6,0xDA,0x69,0xB4,0xDA,0x69,0xB6,0xDA,0x6D,0x24,0xDA,0x6D,0x26,0xDA,0x6D,0x34,0xDA,0x6D,0x36,0xDA,0x6D,0xA4,0xDA,0x6D,0xA6,0xDA,0x6D,0xB4,0xDA,0x6D,0xB6,0xDB,0x49,0x24,0xDB,0x49,0x26,0xDB,0x49,0x34,0xDB,0x49,0x36,0xDB,0x49,0xA4,0xDB,0x49,0xA6,0xDB,0x49,0xB4,0xDB,0x49,0xB6,0xDB,0x4D,0x24,0xDB,0x4D,0x26,0xDB,0x4D,0x34,0xDB,0x4D,0x36,0xDB,0x4D,0xA4,0xDB,0x4D,0xA6,0xDB,0x4D,0xB4,0xDB,0x4D,0xB6,0xDB,0x69,0x24,0xDB,0x69,0x26,0xDB,0x69,0x34,0xDB,0x69,0x36,0xDB,0x69,0xA4,0xDB,0x69,0xA6,0xDB,0x69,0xB4,0xDB,0x69,0xB6,0xDB,0x6D,0x24,0xDB,0x6D,0x26,0xDB,0x6D,0x34,0xDB,0x6D,0x36,0xDB,0x6D,0xA4,0xDB,0x6D,0xA6,0xDB,0x6D,0xB4,0xDB,0x6D,0xB6}; + +class WS2812B { + public: + + // Constructor: number of LEDs + WS2812B (uint16_t number_of_leds);// Constuctor + ~WS2812B(); + void + begin(void), + show(void), + setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b), + // setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w), + setPixelColor(uint16_t n, uint32_t c), + setBrightness(uint8_t), + clear(), + updateLength(uint16_t n); + uint8_t +// *getPixels(void) const, + getBrightness(void) const; + uint16_t + numPixels(void) const; + static uint32_t + Color(uint8_t r, uint8_t g, uint8_t b), + Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w); + // uint32_t + // getPixelColor(uint16_t n) const; + inline bool + canShow(void) { return (micros() - endTime) >= 300L; } + + private: + + boolean + begun; // true if begin() previously called + uint16_t + numLEDs, // Number of RGB LEDs in strip + numBytes; // Size of 'pixels' buffer + + uint8_t + brightness, + *pixels, // Holds the current LED color values, which the external API calls interact with 9 bytes per pixel + start + end empty bytes + *doubleBuffer, // Holds the start of the double buffer (1 buffer for async DMA transfer and one for the API interaction. + rOffset, // Index of red byte within each 3- or 4-byte pixel + gOffset, // Index of green byte + bOffset, // Index of blue byte + wOffset; // Index of white byte (same as rOffset if no white) + uint32_t + endTime; // Latch timing reference +}; + + +#endif // WS2812B_H diff --git a/STM32F1/libraries/Wire/HardWire.cpp b/STM32F1/libraries/Wire/HardWire.cpp deleted file mode 100644 index 8a63183..0000000 --- a/STM32F1/libraries/Wire/HardWire.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file HardWire.cpp - * @author Trystan Jones - * @brief Wire library, uses the hardware I2C available in the Maple to - * interact with I2C slave devices. - */ - -/* - * Library created by crenn to use the new WireBase system and allow Arduino - * users easy interaction with the I2C Hardware in a familiar method. - */ - -#include "HardWire.h" - -uint8 HardWire::process() { - int8 res = i2c_master_xfer(sel_hard, &itc_msg, 1, 0); - if (res == I2C_ERROR_PROTOCOL) { - if (sel_hard->error_flags & I2C_SR1_AF) { /* NACK */ - res = (sel_hard->error_flags & I2C_SR1_ADDR ? ENACKADDR : - ENACKTRNS); - } else if (sel_hard->error_flags & I2C_SR1_OVR) { /* Over/Underrun */ - res = EDATA; - } else { /* Bus or Arbitration error */ - res = EOTHER; - } - i2c_disable(sel_hard); - i2c_master_enable(sel_hard, (I2C_BUS_RESET | dev_flags)); - } - return res; -} - -// TODO: Add in Error Handling if devsel is out of range for other Maples -HardWire::HardWire(uint8 dev_sel, uint8 flags) { - if (dev_sel == 1) { - sel_hard = I2C1; - } else if (dev_sel == 2) { - sel_hard = I2C2; - } else { - ASSERT(1); - } - dev_flags = flags; -} - -HardWire::~HardWire() { - i2c_disable(sel_hard); - sel_hard = 0; -} - -void HardWire::begin(uint8 self_addr) { - i2c_master_enable(sel_hard, dev_flags); -} diff --git a/STM32F1/libraries/Wire/HardWire.h b/STM32F1/libraries/Wire/HardWire.h deleted file mode 100644 index 6f137b8..0000000 --- a/STM32F1/libraries/Wire/HardWire.h +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file HardWire.h - * @author Trystan Jones - * @brief Wire library, uses the hardware I2C available in the Maple to - * interact with I2C slave devices. - */ - -/* - * Library created by crenn to use the new WireBase system and allow Arduino - * users easy interaction with the I2C Hardware in a familiar method. - */ - -#ifndef _HARDWIRE_H_ -#define _HARDWIRE_H_ - -#include "WireBase.h" -#include "wirish.h" -#include - -class HardWire : public WireBase { -private: - i2c_dev* sel_hard; - uint8 dev_flags; -protected: - /* - * Processes the incoming I2C message defined by WireBase to the - * hardware. If an error occured, restart the I2C device. - */ - uint8 process(); -public: - /* - * Check if devsel is within range and enable selected I2C interface with - * passed flags - */ - HardWire(uint8, uint8 = 0); - - /* - * Disables the I2C device and remove the device address. - */ - ~HardWire(); - - void begin(uint8 = 0x00); -}; -extern HardWire HWire; -#endif // _HARDWIRE_H_ diff --git a/STM32F1/libraries/Wire/SoftWire.cpp b/STM32F1/libraries/Wire/SoftWire.cpp new file mode 100644 index 0000000..4e3cdd5 --- /dev/null +++ b/STM32F1/libraries/Wire/SoftWire.cpp @@ -0,0 +1,246 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file SoftWire.cpp + * @author Trystan Jones + * @brief Wire library, uses the WireBase to create the primary interface + * while keeping low level interactions invisible to the user. + */ + +/* + * Library updated by crenn to follow new Wire system. + * Code was derived from the original Wire for maple code by leaflabs and the + * modifications by gke and ala42. + */ + /* + * Updated by Roger Clark. 20141111. Fixed issue when process() returned because of missing ACK (often caused by invalid device address being used), caused SCL to be left + * LOW so that in the next call to process() , the first clock pulse was not sent, because SCL was LOW when it should have been high. + */ + /* + * Updated by Brandon Green. 20172306. Implementing the repeated start functionality. + */ + +#include "SoftWire.h" + +#define I2C_WRITE 0 +#define I2C_READ 1 + +/* low level conventions: + * - SDA/SCL idle high (expected high) + * - always start with i2c_delay rather than end + */ + +void SoftWire::set_scl(bool state) { + I2C_DELAY(this->i2c_delay); + + gpio_write_bit(sclDevice,sclBit, state); +// digitalWrite(this->scl_pin,state); + //Allow for clock stretching - dangerous currently + if (state == HIGH) { + while(digitalRead(this->scl_pin) == 0); + } +} + +void SoftWire::set_sda(bool state) { + I2C_DELAY(this->i2c_delay); + gpio_write_bit(sdaDevice,sdaBit, state); + //digitalWrite(this->sda_pin, state); +} + +void SoftWire::i2c_start() { + set_sda(LOW); + set_scl(LOW); +} + +void SoftWire::i2c_stop() { + set_sda(LOW); + set_scl(HIGH); + set_sda(HIGH); +} + +void SoftWire::i2c_repeated_start() { + set_sda(HIGH); + set_scl(HIGH); + set_sda(LOW); +} + +bool SoftWire::i2c_get_ack() { + set_scl(LOW); + set_sda(HIGH); + set_scl(HIGH); + + bool ret = !digitalRead(this->sda_pin); + set_scl(LOW); + return ret; +} + +void SoftWire::i2c_send_ack() { + set_sda(LOW); + set_scl(HIGH); + set_scl(LOW); +} + +void SoftWire::i2c_send_nack() { + set_sda(HIGH); + set_scl(HIGH); + set_scl(LOW); +} + +uint8 SoftWire::i2c_shift_in() { + uint8 data = 0; + set_sda(HIGH); + + int i; + for (i = 0; i < 8; i++) { + set_scl(HIGH); + data |= digitalRead(this->sda_pin) << (7-i); + set_scl(LOW); + } + + return data; +} + +void SoftWire::i2c_shift_out(uint8 val) { + int i; + for (i = 0; i < 8; i++) { + set_sda(!!(val & (1 << (7 - i)) ) ); + set_scl(HIGH); + set_scl(LOW); + } +} + +//process needs to be updated for repeated start. +uint8 SoftWire::process(uint8 stop) { + itc_msg.xferred = 0; + + uint8 sla_addr = (itc_msg.addr << 1); + if (itc_msg.flags == I2C_MSG_READ) { + sla_addr |= I2C_READ; + } + i2c_start(); + // shift out the address we're transmitting to + i2c_shift_out(sla_addr); + if (!i2c_get_ack()) + { + i2c_stop();// Roger Clark. 20141110 added to set clock high again, as it will be left in a low state otherwise + return ENACKADDR; + } + // Recieving + if (itc_msg.flags == I2C_MSG_READ) { + while (itc_msg.xferred < itc_msg.length) { + itc_msg.data[itc_msg.xferred++] = i2c_shift_in(); + if (itc_msg.xferred < itc_msg.length) + { + i2c_send_ack(); + } + else + { + i2c_send_nack(); + } + } + } + // Sending + else { + for (uint8 i = 0; i < itc_msg.length; i++) { + i2c_shift_out(itc_msg.data[i]); + if (!i2c_get_ack()) + { + i2c_stop();// Roger Clark. 20141110 added to set clock high again, as it will be left in a low state otherwise + return ENACKTRNS; + } + itc_msg.xferred++; + } + } + if(stop == true) + i2c_stop(); + else i2c_repeated_start(); + + return SUCCESS; +} + +// For compatibility with legacy code +uint8 SoftWire::process(){ + return process(true); +} + +// TODO: Add in Error Handling if pins is out of range for other Maples +// TODO: Make delays more capable +SoftWire::SoftWire(uint8 scl, uint8 sda, uint8 delay) : i2c_delay(delay) { + this->scl_pin=scl; + this->sda_pin=sda; +} + +void SoftWire::begin(uint8 self_addr) { + tx_buf_idx = 0; + tx_buf_overflow = false; + rx_buf_idx = 0; + rx_buf_len = 0; + pinMode(this->scl_pin, OUTPUT_OPEN_DRAIN); + pinMode(this->sda_pin, OUTPUT_OPEN_DRAIN); + + sclDevice = PIN_MAP[this->scl_pin].gpio_device; + sclBit = PIN_MAP[this->scl_pin].gpio_bit; + sdaDevice = PIN_MAP[this->sda_pin].gpio_device; + sdaBit = PIN_MAP[this->sda_pin].gpio_bit; + set_scl(HIGH); + set_sda(HIGH); +} + +void SoftWire::end() +{ + if (this->scl_pin) + { + pinMode(this->scl_pin, INPUT); + } + if (this->sda_pin) + { + pinMode(this->sda_pin, INPUT); + } +} + +void SoftWire::setClock(uint32_t frequencyHz) +{ + switch(frequencyHz) + { + case 400000: + i2c_delay = SOFT_FAST; + break; + case 100000: + default: + i2c_delay = SOFT_STANDARD; + break; + } +} + +SoftWire::~SoftWire() { + this->scl_pin=0; + this->sda_pin=0; +} + +// Declare the instance that the users of the library can use +//SoftWire Wire(SCL, SDA, SOFT_STANDARD); +//SoftWire Wire(PB6, PB7, SOFT_FAST); diff --git a/STM32F1/libraries/Wire/SoftWire.h b/STM32F1/libraries/Wire/SoftWire.h new file mode 100644 index 0000000..c42bca4 --- /dev/null +++ b/STM32F1/libraries/Wire/SoftWire.h @@ -0,0 +1,163 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file SoftWire.h + * @author Trystan Jones + * @brief Wire library, uses the WireBase to create the primary interface + * while keeping low level interactions invisible to the user. + */ + +/* + * Library updated by crenn to follow new Wire system. + * Code was derived from the original Wire for maple code by leaflabs and the + * modifications by gke and ala42. + */ + +#ifndef _SOFTWIRE_H_ +#define _SOFTWIRE_H_ + +#include "utility/WireBase.h" +#include "wirish.h" + +/* + * On the Maple, let the default pins be in the same location as the Arduino + * pins + */ +#define SDA PB7 +#define SCL PB6 + +#define SOFT_STANDARD 19 +#define SOFT_FAST 0 + + +//#define I2C_DELAY(x) {uint32 time=micros(); while(time>(micros()+x));} +#define I2C_DELAY(x) do{for(int i=0;i - * @brief Wire library, uses the WireBase to create the primary interface - * while keeping low level interactions invisible to the user. + * @brief Wire library, uses the hardware I2C available in the Maple to + * interact with I2C slave devices. */ /* - * Library updated by crenn to follow new Wire system. - * Code was derived from the original Wire for maple code by leaflabs and the - * modifications by gke and ala42. + * Library created by crenn to use the new WireBase system and allow Arduino + * users easy interaction with the I2C Hardware in a familiar method. */ - /* - * Updated by Roger Clark. 20141111. Fixed issue when process() returned because of missing ACK (often caused by invalid device address being used), caused SCL to be left - * LOW so that in the next call to process() , the first clock pulse was not sent, because SCL was LOW when it should have been high. - */ #include "Wire.h" -#define I2C_WRITE 0 -#define I2C_READ 1 - -/* low level conventions: - * - SDA/SCL idle high (expected high) - * - always start with i2c_delay rather than end - */ - -void TwoWire::set_scl(bool state) { - I2C_DELAY(this->i2c_delay); - digitalWrite(this->scl_pin,state); - //Allow for clock stretching - dangerous currently - if (state == HIGH) { - while(digitalRead(this->scl_pin) == 0); - } -} - -void TwoWire::set_sda(bool state) { - I2C_DELAY(this->i2c_delay); - digitalWrite(this->sda_pin, state); -} - -void TwoWire::i2c_start() { - set_sda(LOW); - set_scl(LOW); -} - -void TwoWire::i2c_stop() { - set_sda(LOW); - set_scl(HIGH); - set_sda(HIGH); -} - -bool TwoWire::i2c_get_ack() { - set_scl(LOW); - set_sda(HIGH); - set_scl(HIGH); - - bool ret = !digitalRead(this->sda_pin); - set_scl(LOW); - return ret; -} - -void TwoWire::i2c_send_ack() { - set_sda(LOW); - set_scl(HIGH); - set_scl(LOW); -} - -void TwoWire::i2c_send_nack() { - set_sda(HIGH); - set_scl(HIGH); - set_scl(LOW); -} - -uint8 TwoWire::i2c_shift_in() { - uint8 data = 0; - set_sda(HIGH); - - int i; - for (i = 0; i < 8; i++) { - set_scl(HIGH); - data |= digitalRead(this->sda_pin) << (7-i); - set_scl(LOW); - } - - return data; -} - -void TwoWire::i2c_shift_out(uint8 val) { - int i; - for (i = 0; i < 8; i++) { - set_sda(!!(val & (1 << (7 - i)) ) ); - set_scl(HIGH); - set_scl(LOW); - } -} - -uint8 TwoWire::process() { - itc_msg.xferred = 0; - - uint8 sla_addr = (itc_msg.addr << 1); - if (itc_msg.flags == I2C_MSG_READ) { - sla_addr |= I2C_READ; - } - i2c_start(); - // shift out the address we're transmitting to - i2c_shift_out(sla_addr); - if (!i2c_get_ack()) - { - i2c_stop();// Roger Clark. 20141110 added to set clock high again, as it will be left in a low state otherwise - return ENACKADDR; - } - // Recieving - if (itc_msg.flags == I2C_MSG_READ) { - while (itc_msg.xferred < itc_msg.length) { - itc_msg.data[itc_msg.xferred++] = i2c_shift_in(); - if (itc_msg.xferred < itc_msg.length) - { - i2c_send_ack(); - } - else - { - i2c_send_nack(); - } +uint8 TwoWire::process(uint8 stop) { + int8 res = i2c_master_xfer(sel_hard, &itc_msg, 1, 0); + if (res == I2C_ERROR_PROTOCOL) { + if (sel_hard->error_flags & I2C_SR1_AF) { /* NACK */ + res = (sel_hard->error_flags & I2C_SR1_ADDR ? ENACKADDR : + ENACKTRNS); + } else if (sel_hard->error_flags & I2C_SR1_OVR) { /* Over/Underrun */ + res = EDATA; + } else { /* Bus or Arbitration error */ + res = EOTHER; } + i2c_disable(sel_hard); + i2c_master_enable(sel_hard, dev_flags); } - // Sending - else { - for (uint8 i = 0; i < itc_msg.length; i++) { - i2c_shift_out(itc_msg.data[i]); - if (!i2c_get_ack()) - { - i2c_stop();// Roger Clark. 20141110 added to set clock high again, as it will be left in a low state otherwise - return ENACKTRNS; - } - itc_msg.xferred++; - } - } - i2c_stop(); - return SUCCESS; + return res; } -// TODO: Add in Error Handling if pins is out of range for other Maples -// TODO: Make delays more capable -TwoWire::TwoWire(uint8 scl, uint8 sda, uint8 delay) : i2c_delay(delay) { - this->scl_pin=scl; - this->sda_pin=sda; +uint8 TwoWire::process(){ + return process(true); } -void TwoWire::begin(uint8 self_addr) { - tx_buf_idx = 0; - tx_buf_overflow = false; - rx_buf_idx = 0; - rx_buf_len = 0; - pinMode(this->scl_pin, OUTPUT_OPEN_DRAIN); - pinMode(this->sda_pin, OUTPUT_OPEN_DRAIN); - set_scl(HIGH); - set_sda(HIGH); +// TODO: Add in Error Handling if devsel is out of range for other Maples +TwoWire::TwoWire(uint8 dev_sel, uint8 flags) { + if (dev_sel == 1) { + sel_hard = I2C1; + } else if (dev_sel == 2) { + sel_hard = I2C2; + } else { + ASSERT(1); + } + dev_flags = flags; } TwoWire::~TwoWire() { - this->scl_pin=0; - this->sda_pin=0; + i2c_disable(sel_hard); + sel_hard = 0; } -// Declare the instance that the users of the library can use -TwoWire Wire(SCL, SDA, SOFT_STANDARD); -//TwoWire Wire(PB6, PB7, SOFT_STANDARD); +void TwoWire::begin(uint8 self_addr) { + i2c_master_enable(sel_hard, dev_flags); +} + +void TwoWire::end() { + i2c_disable(sel_hard); + sel_hard = 0; +} + +void TwoWire::setClock(uint32_t frequencyHz) +{ + switch(frequencyHz) + { + case 400000: + dev_flags |= I2C_FAST_MODE;// set FAST_MODE bit + break; + case 100000: + default: + dev_flags &= ~I2C_FAST_MODE;// clear FAST_MODE bit + break; + } + if (sel_hard->regs->CR1 & I2C_CR1_PE){ + i2c_disable(sel_hard); + i2c_master_enable(sel_hard, dev_flags); + } +} + +TwoWire Wire(1); diff --git a/STM32F1/libraries/Wire/Wire.h b/STM32F1/libraries/Wire/Wire.h index add0ac9..ab05d42 100644 --- a/STM32F1/libraries/Wire/Wire.h +++ b/STM32F1/libraries/Wire/Wire.h @@ -27,115 +27,52 @@ /** * @file Wire.h * @author Trystan Jones - * @brief Wire library, uses the WireBase to create the primary interface - * while keeping low level interactions invisible to the user. + * @brief Wire library, uses the hardware I2C available in the Maple to + * interact with I2C slave devices. */ /* - * Library updated by crenn to follow new Wire system. - * Code was derived from the original Wire for maple code by leaflabs and the - * modifications by gke and ala42. + * Library created by crenn to use the new WireBase system and allow Arduino + * users easy interaction with the I2C Hardware in a familiar method. */ -#ifndef _WIRE_H_ -#define _WIRE_H_ +#ifndef _TWOWIRE_H_ +#define _TWOWIRE_H_ -#include "WireBase.h" +#include "utility/WireBase.h" #include "wirish.h" - -/* - * On the Maple, let the default pins be in the same location as the Arduino - * pins - */ -#define SDA PB7 -#define SCL PB6 - -#define SOFT_STANDARD 27 -#define SOFT_FAST 0 - - -//#define I2C_DELAY(x) {uint32 time=micros(); while(time>(micros()+x));} -#define I2C_DELAY(x) do{for(int i=0;i class TwoWire : public WireBase { - public: - uint8 i2c_delay; - uint8 scl_pin; - uint8 sda_pin; - +private: + i2c_dev* sel_hard; + uint8 dev_flags; +protected: /* - * Sets the SCL line to HIGH/LOW and allow for clock stretching by slave - * devices - */ - void set_scl(bool); - - /* - * Sets the SDA line to HIGH/LOW - */ - void set_sda(bool); - - /* - * Creates a Start condition on the bus - */ - void i2c_start(); - - /* - * Creates a Stop condition on the bus - */ - void i2c_stop(); - - /* - * Gets an ACK condition from a slave device on the bus - */ - bool i2c_get_ack(); - - /* - * Creates a ACK condition on the bus - */ - void i2c_send_ack(); - - /* - * Creates a NACK condition on the bus - */ - void i2c_send_nack(); - - /* - * Shifts in the data through SDA and clocks SCL for the slave device - */ - uint8 i2c_shift_in(); - - /* - * Shifts out the data through SDA and clocks SCL for the slave device - */ - void i2c_shift_out(uint8); - protected: - /* - * Processes the incoming I2C message defined by WireBase + * Processes the incoming I2C message defined by WireBase to the + * hardware. If an error occured, restart the I2C device. */ + uint8 process(uint8); uint8 process(); - public: +public: /* - * Accept pin numbers for SCL and SDA lines. Set the delay needed - * to create the timing for I2C's Standard Mode and Fast Mode. + * Check if devsel is within range and enable selected I2C interface with + * passed flags */ - TwoWire(uint8 scl=SCL, uint8 sda=SDA, uint8 delay=SOFT_STANDARD); + TwoWire(uint8, uint8 = 0); + + /* + * Shuts down (disables) the hardware I2C + */ + void end(); + void setClock(uint32_t frequencyHz); /* - * Sets pins SDA and SCL to OUPTUT_OPEN_DRAIN, joining I2C bus as - * master. This function overwrites the default behaviour of - * .begin(uint8) in WireBase - */ - void begin(uint8 = 0x00); - - /* - * If object is destroyed, set pin numbers to 0. + * Disables the I2C device and remove the device address. */ ~TwoWire(); + + void begin(uint8 = 0x00); }; - extern TwoWire Wire; - -#endif // _WIRE_H_ +#endif // _TWOWIRE_H_ diff --git a/STM32F1/libraries/Wire/Wire_slave.h b/STM32F1/libraries/Wire/Wire_slave.h new file mode 100644 index 0000000..ede963b --- /dev/null +++ b/STM32F1/libraries/Wire/Wire_slave.h @@ -0,0 +1 @@ +#error "Something is trying to include Wire_slave.h when Wire.h is already included, they are mutually exclusive" diff --git a/STM32F1/libraries/Wire/examples/i2c_scanner_softwire/i2c_scanner_softwire.ino b/STM32F1/libraries/Wire/examples/i2c_scanner_softwire/i2c_scanner_softwire.ino new file mode 100644 index 0000000..f6bf685 --- /dev/null +++ b/STM32F1/libraries/Wire/examples/i2c_scanner_softwire/i2c_scanner_softwire.ino @@ -0,0 +1,54 @@ +// -------------------------------------- +// i2c_scanner +// +// + +#include + +SoftWire SWire(PB6, PB7, SOFT_FAST); + + +void setup() { + Serial.begin(115200); + SWire.begin(); + Serial.println("\nSoftware I2C.. Scanner"); +} + + +void loop() { + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 1; address < 127; address++) { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + + SWire.beginTransmission(address); + error = SWire.endTransmission(); + + if (error == 0) { + Serial.print("I2C device found at address 0x"); + if (address < 16) + Serial.print("0"); + Serial.println(address, HEX); + + nDevices++; + } + else if (error == 4) { + Serial.print("Unknown error at address 0x"); + if (address < 16) + Serial.print("0"); + Serial.println(address, HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found"); + else + Serial.println("done"); + + delay(5000); // wait 5 seconds for next scan +} \ No newline at end of file diff --git a/STM32F1/libraries/Wire/examples/i2c_scanner_wire/i2c_scanner_wire.ino b/STM32F1/libraries/Wire/examples/i2c_scanner_wire/i2c_scanner_wire.ino index 30224d2..0367b4e 100644 --- a/STM32F1/libraries/Wire/examples/i2c_scanner_wire/i2c_scanner_wire.ino +++ b/STM32F1/libraries/Wire/examples/i2c_scanner_wire/i2c_scanner_wire.ino @@ -26,6 +26,10 @@ #include +//use IIC2 +//TwoWire WIRE2 (2,I2C_FAST_MODE); +//#define Wire WIRE2 + void setup() { @@ -71,4 +75,4 @@ void loop() { Serial.println("done"); delay(5000); // wait 5 seconds for next scan -} \ No newline at end of file +} diff --git a/STM32F1/libraries/Wire/keywords.txt b/STM32F1/libraries/Wire/keywords.txt new file mode 100644 index 0000000..4234cc5 --- /dev/null +++ b/STM32F1/libraries/Wire/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Datatypes (KEYWORD1) +####################################### +TwoWire KEYWORD1 +SoftWire KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + + + +####################################### +# Constants (LITERAL1) +####################################### +SOFT_STANDARD LITERAL1 +SOFT_FAST LITERAL1 +I2C_FAST_MODE LITERAL1 \ No newline at end of file diff --git a/STM32F1/libraries/Wire/library.properties b/STM32F1/libraries/Wire/library.properties new file mode 100644 index 0000000..06b7aee --- /dev/null +++ b/STM32F1/libraries/Wire/library.properties @@ -0,0 +1,10 @@ +name=Wire +version=1.0 +author=Roger Clark +maintainer= +sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. +paragraph= +category=Communication +url=http://www.arduino.cc/en/Reference/Wire +architectures=STM32F1 +include=Wire.h,SoftWire.h diff --git a/STM32F1/libraries/Wire/rules.mk b/STM32F1/libraries/Wire/rules.mk index e16f4db..2b33332 100644 --- a/STM32F1/libraries/Wire/rules.mk +++ b/STM32F1/libraries/Wire/rules.mk @@ -1,3 +1,7 @@ +#this makefile may not work since HardWire has been changed to the default Wire (TwoWire) +#anyway this file should be useless + + # Standard things sp := $(sp).x dirstack_$(sp) := $(d) diff --git a/STM32F1/libraries/Wire/WireBase.cpp b/STM32F1/libraries/Wire/utility/WireBase.cpp similarity index 84% rename from STM32F1/libraries/Wire/WireBase.cpp rename to STM32F1/libraries/Wire/utility/WireBase.cpp index ff0dae3..5d4f63b 100644 --- a/STM32F1/libraries/Wire/WireBase.cpp +++ b/STM32F1/libraries/Wire/utility/WireBase.cpp @@ -59,23 +59,27 @@ void WireBase::beginTransmission(int slave_address) { beginTransmission((uint8)slave_address); } -uint8 WireBase::endTransmission(void) { +uint8 WireBase::endTransmission(bool stop) { uint8 retVal; if (tx_buf_overflow) { return EDATA; } - retVal = process();// Changed so that the return value from process is returned by this function see also the return line below + retVal = process(stop);// Changed so that the return value from process is returned by this function see also the return line below tx_buf_idx = 0; tx_buf_overflow = false; return retVal;//SUCCESS; } +uint8 WireBase::endTransmission(){ + return endTransmission(true); +} + //TODO: Add the ability to queue messages (adding a boolean to end of function // call, allows for the Arduino style to stay while also giving the flexibility // to bulk send uint8 WireBase::requestFrom(uint8 address, int num_bytes) { - if (num_bytes > WIRE_BUFSIZ) { - num_bytes = WIRE_BUFSIZ; + if (num_bytes > BUFFER_LENGTH) { + num_bytes = BUFFER_LENGTH; } itc_msg.addr = address; itc_msg.flags = I2C_MSG_READ; @@ -91,27 +95,33 @@ uint8 WireBase::requestFrom(int address, int numBytes) { return WireBase::requestFrom((uint8)address, numBytes); } -void WireBase::write(uint8 value) { - if (tx_buf_idx == WIRE_BUFSIZ) { +size_t WireBase::write(uint8 value) { + if (tx_buf_idx == BUFFER_LENGTH) { tx_buf_overflow = true; - return; + return 0; } tx_buf[tx_buf_idx++] = value; itc_msg.length++; + return 1; } -void WireBase::write(uint8* buf, int len) { +size_t WireBase::write(uint8* buf, int len) { for (uint8 i = 0; i < len; i++) { - write(buf[i]); + if (!write(buf[i])) + { + return i; + } } + return len; } -void WireBase::write(int value) { - write((uint8)value); + +size_t WireBase::write(int value) { + return write((uint8)value); } -void WireBase::write(int* buf, int len) { - write((uint8*)buf, (uint8)len); +size_t WireBase::write(int* buf, int len) { + return write((uint8*)buf, (uint8)len); } void WireBase::write(char* buf) { diff --git a/STM32F1/libraries/Wire/WireBase.h b/STM32F1/libraries/Wire/utility/WireBase.h similarity index 92% rename from STM32F1/libraries/Wire/WireBase.h rename to STM32F1/libraries/Wire/utility/WireBase.h index 4e51c0d..b543a15 100644 --- a/STM32F1/libraries/Wire/WireBase.h +++ b/STM32F1/libraries/Wire/utility/WireBase.h @@ -44,7 +44,7 @@ #include "wirish.h" #include -#define WIRE_BUFSIZ 32 +#define BUFFER_LENGTH 32 /* return codes from endTransmission() */ #define SUCCESS 0 /* transmission was successful */ @@ -56,15 +56,16 @@ class WireBase { // Abstraction is awesome! protected: i2c_msg itc_msg; - uint8 rx_buf[WIRE_BUFSIZ]; /* receive buffer */ + uint8 rx_buf[BUFFER_LENGTH]; /* receive buffer */ uint8 rx_buf_idx; /* first unread idx in rx_buf */ uint8 rx_buf_len; /* number of bytes read */ - uint8 tx_buf[WIRE_BUFSIZ]; /* transmit buffer */ + uint8 tx_buf[BUFFER_LENGTH]; /* transmit buffer */ uint8 tx_buf_idx; // next idx available in tx_buf, -1 overflow boolean tx_buf_overflow; // Force derived classes to define process function + virtual uint8 process(uint8) = 0; virtual uint8 process() = 0; public: WireBase() {} @@ -90,6 +91,7 @@ public: * Call the process function to process the message if the TX * buffer has not overflowed. */ + uint8 endTransmission(bool); uint8 endTransmission(void); /* @@ -106,22 +108,22 @@ public: /* * Stack up bytes to be sent when transmitting */ - void write(uint8); + size_t write(uint8); /* * Stack up bytes from the array to be sent when transmitting */ - void write(uint8*, int); + size_t write(uint8*, int); /* * Ensure that a sending data will only be 8-bit bytes */ - void write(int); + size_t write(int); /* * Ensure that an array sending data will only be 8-bit bytes */ - void write(int*, int); + size_t write(int*, int); /* * Stack up bytes from a string to be sent when transmitting diff --git a/STM32F1/libraries/WireSlave/examples/SFRRanger_reader/SFRRanger_reader.ino b/STM32F1/libraries/WireSlave/examples/SFRRanger_reader/SFRRanger_reader.ino new file mode 100644 index 0000000..9409bb1 --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/SFRRanger_reader/SFRRanger_reader.ino @@ -0,0 +1,87 @@ +// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder +// by Nicholas Zambetti +// and James Tichenor + +// Demonstrates use of the Wire library reading data from the +// Devantech Utrasonic Rangers SFR08 and SFR10 + +// Created 29 April 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) + Serial.begin(115200); // start serial communication at 9600bps +} + +int reading = 0; + +void loop() +{ + // step 1: instruct sensor to read echoes + Wire.beginTransmission(112); // transmit to device #112 (0x70) + // the address specified in the datasheet is 224 (0xE0) + // but i2c adressing uses the high 7 bits so it's 112 + Wire.write(byte(0x00)); // sets register pointer to the command register (0x00) + Wire.write(byte(0x50)); // command sensor to measure in "inches" (0x50) + // use 0x51 for centimeters + // use 0x52 for ping microseconds + Wire.endTransmission(); // stop transmitting + + // step 2: wait for readings to happen + delay(70); // datasheet suggests at least 65 milliseconds + + // step 3: instruct sensor to return a particular echo reading + Wire.beginTransmission(112); // transmit to device #112 + Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02) + Wire.endTransmission(); // stop transmitting + + // step 4: request reading from sensor + Wire.requestFrom(112, 2); // request 2 bytes from slave device #112 + + // step 5: receive reading from sensor + if(2 <= Wire.available()) // if two bytes were received + { + reading = Wire.read(); // receive high byte (overwrites previous reading) + reading = reading << 8; // shift high byte to be high 8 bits + reading |= Wire.read(); // receive low byte as lower 8 bits + Serial.println(reading); // print the reading + } + + delay(250); // wait a bit since people have to read the output :) +} + + +/* + +// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08) +// usage: changeAddress(0x70, 0xE6); + +void changeAddress(byte oldAddress, byte newAddress) +{ + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xA0)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xAA)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xA5)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(newAddress); + Wire.endTransmission(); +} + +*/ diff --git a/STM32F1/libraries/WireSlave/examples/digital_potentiometer/digital_potentiometer.ino b/STM32F1/libraries/WireSlave/examples/digital_potentiometer/digital_potentiometer.ino new file mode 100644 index 0000000..8830ada --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/digital_potentiometer/digital_potentiometer.ino @@ -0,0 +1,38 @@ +// I2C Digital Potentiometer +// by Nicholas Zambetti +// and Shawn Bonkowski + +// Demonstrates use of the Wire library +// Controls AD5171 digital potentiometer via I2C/TWI + +// Created 31 March 2006 + +// This example code is in the public domain. + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) +} + +byte val = 0; + +void loop() +{ + Wire.beginTransmission(44); // transmit to device #44 (0x2c) + // device address is specified in datasheet + Wire.write(byte(0x00)); // sends instruction byte + Wire.write(val); // sends potentiometer value byte + Wire.endTransmission(); // stop transmitting + + val++; // increment value + if(val == 64) // if reached 64th position (max) + { + val = 0; // start over from lowest value + } + delay(500); +} diff --git a/STM32F1/libraries/WireSlave/examples/i2c_libmaple_slave_reader/i2c_libmaple_slave_reader.ino b/STM32F1/libraries/WireSlave/examples/i2c_libmaple_slave_reader/i2c_libmaple_slave_reader.ino new file mode 100644 index 0000000..fd059c1 --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/i2c_libmaple_slave_reader/i2c_libmaple_slave_reader.ino @@ -0,0 +1,118 @@ +/* +* i2c_slave example.cpp +* +* You can use this sketch in combination with master_writer.pde +* +* Created on: 4 Sep 2012 +* Author: Barry Carter +*/ +#include +#include + +#define USE_BUFFERED_EXAMPLE 1 + +i2c_msg msg; +uint8 buffer[255]; +char* const bufferAsChar = (char*)buffer; // ready type casted alias + +volatile bool newMessage = false; + +void funcrx(i2c_msg *msg __attribute__((unused))){ + // Received length will be in msg->length + newMessage = true; +} + +#if USE_BUFFERED_EXAMPLE == 1 +/* We ARE using a buffer to transmit the data out. +* Make sure you fill the buffer with the data AND you set the length correctly +*/ +void functx(i2c_msg *msg){ + // Cheeky. We are using the received byte of the data which is currently in + // byte 0 to echo it back to the master device + //msg->data[0] = 0x01; // We are re-using the rx buffer here to echo the request back + msg->data[1] = 0x02; + msg->data[2] = 0x03; + msg->data[3] = 0x04; + msg->data[4] = 0x05; + msg->length = 5; +} + +#else + +/* We are NOT using the buffered data transmission +* We will get this callback for each outgoing packet. Make sure to call i2c_write +* Strickly speaking, we should be sending a NACk on the last byte we want to send +* but for this test example I am going to assume the master will NACK it when it +* wants to stop. +*/ +void functx(i2c_msg *msg){ + i2c_write(I2C1, msg->data[0]); +} + +#endif + +void setup() { + Serial.begin(115200); + Serial.println("libmaple I2C slave reader example"); + + // attach the buffer + msg.data = buffer; + + /* Init slave mode. Enables master too + * We are going to configure the slave device to + * - enable fast I2C (400khz) + * - dual addresses (can have 2 addresses per module) + * general call (accepts data writes to 0x00 on a broadcast basis) + * + * If the buffered example is enabled, then we also enable the + * buffer for rx and tx. + * Note you can independently enable/disable RX and TX buffers to + * allow a buffered read and direct writes. Useful if you don't know how + * much the master will read. + */ + #if USE_BUFFERED_EXAMPLE == 1 + i2c_slave_enable(I2C1, I2C_FAST_MODE | I2C_SLAVE_DUAL_ADDRESS | I2C_SLAVE_GENERAL_CALL | I2C_SLAVE_USE_RX_BUFFER | I2C_SLAVE_USE_TX_BUFFER); + #else + i2c_slave_enable(I2C1, I2C_FAST_MODE | I2C_SLAVE_DUAL_ADDRESS | I2C_SLAVE_GENERAL_CALL); + #endif + + // attach receive handler + i2c_slave_attach_recv_handler(I2C1, &msg, funcrx); + // attach transmit handler + i2c_slave_attach_transmit_handler(I2C1, &msg, functx); + + // set addresss to 4 + i2c_slave_set_own_address(I2C1, 4); +} + +void loop() { + static uint32_t lastMessage = millis(); + + // This is potentially dangerous. + // We're reading from the live buffer, the content can change + // in the middle of Serial.println + + if (newMessage && strlen(bufferAsChar)==6) { + for (int i=0; i<5; i++) { + // Print as char + Serial.print(bufferAsChar[i]); + } + // Print as byte + Serial.println(buffer[5]); + lastMessage = millis(); + newMessage = false; + } else { + if(newMessage && strlen(bufferAsChar)!=6) { + // this also happends on the line "x is 0" + Serial.print("Bad data received:"); + Serial.println(bufferAsChar); + Serial.print("strlen:"); + Serial.println(strlen(bufferAsChar)); + newMessage = false; + } else + if(millis() - lastMessage > 3000){ + Serial.println("Nothing received in 3 seconds."); + lastMessage = millis(); + } + } +} diff --git a/STM32F1/libraries/Wire/examples/i2c_scanner_hwire/i2c_scanner_hwire.ino b/STM32F1/libraries/WireSlave/examples/i2c_scanner_wire/i2c_scanner_wire.ino similarity index 88% rename from STM32F1/libraries/Wire/examples/i2c_scanner_hwire/i2c_scanner_hwire.ino rename to STM32F1/libraries/WireSlave/examples/i2c_scanner_wire/i2c_scanner_wire.ino index 745cae6..44af4dc 100644 --- a/STM32F1/libraries/Wire/examples/i2c_scanner_hwire/i2c_scanner_hwire.ino +++ b/STM32F1/libraries/WireSlave/examples/i2c_scanner_wire/i2c_scanner_wire.ino @@ -19,20 +19,22 @@ // Version 5, March 28, 2013 // As version 4, but address scans now to 127. // A sensor seems to use address 120. -// Version 6, August 1, 2015 -// Modified to support HardWire for STM32duino // // This sketch tests the standard 7-bit addresses // Devices with higher bit address might not be seen properly. // -#include +#include + +//use IIC2 +//TwoWire WIRE2 (2,I2C_FAST_MODE); +//#define Wire WIRE2 -HardWire HWire(1, I2C_FAST_MODE); // I2c1 void setup() { + Serial.begin(115200); - HWire.begin(); + Wire.begin(); Serial.println("\nI2C Scanner"); } @@ -49,8 +51,8 @@ void loop() { // the Write.endTransmisstion to see if // a device did acknowledge to the address. - HWire.beginTransmission(address); - error = HWire.endTransmission(); + Wire.beginTransmission(address); + error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); @@ -73,4 +75,4 @@ void loop() { Serial.println("done"); delay(5000); // wait 5 seconds for next scan -} \ No newline at end of file +} diff --git a/STM32F1/libraries/WireSlave/examples/master_reader/master_reader.ino b/STM32F1/libraries/WireSlave/examples/master_reader/master_reader.ino new file mode 100644 index 0000000..bd914e3 --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/master_reader/master_reader.ino @@ -0,0 +1,32 @@ +// Wire Master Reader +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Reads data from an I2C/TWI slave device +// Refer to the "Wire Slave Sender" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) + Serial.begin(115200); // start serial for output +} + +void loop() +{ + Wire.requestFrom(8, 6); // request 6 bytes from slave device #8 + + while(Wire.available()) // slave may send less than requested + { + char c = Wire.read(); // receive a byte as character + Serial.print(c); // print the character + } + + delay(500); +} diff --git a/STM32F1/libraries/WireSlave/examples/master_writer/master_writer.ino b/STM32F1/libraries/WireSlave/examples/master_writer/master_writer.ino new file mode 100644 index 0000000..f997473 --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/master_writer/master_writer.ino @@ -0,0 +1,31 @@ +// Wire Master Writer +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Writes data to an I2C/TWI slave device +// Refer to the "Wire Slave Receiver" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) +} + +byte x = 0; + +void loop() +{ + Wire.beginTransmission(4); // transmit to device #4 + Wire.write("x is "); // sends five bytes + Wire.write(x); // sends one byte + Wire.endTransmission(); // stop transmitting + + x++; + delay(500); +} diff --git a/STM32F1/libraries/WireSlave/examples/selftest1/code.cpp b/STM32F1/libraries/WireSlave/examples/selftest1/code.cpp new file mode 100644 index 0000000..d2bce8c --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/selftest1/code.cpp @@ -0,0 +1,68 @@ +// Wire Slave Receiver +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + +#include +//#define Serial Serial1 + +#define MasterWire Wire +#define SlaveWire Wire1 +#define ENABLE_SLAVE +#define ENABLE_MASTER + +void receiveEvent(int howMany); + +void setup(){ + Serial.begin(115200); // start serial for output + + #ifdef ENABLE_MASTER + MasterWire.begin(); // join i2c bus #1 as master + Serial.println("Done with MasterWire.begin "); + #endif + + #ifdef ENABLE_SLAVE + SlaveWire.begin(4); // join i2c bus #2 as slave with address #4 + Serial.println("Done with SlaveWire.begin "); + #endif + + #ifdef ENABLE_SLAVE + SlaveWire.onReceive(receiveEvent); // register event + #endif +} + +void loop(){ + #ifdef ENABLE_MASTER + static byte x = 0; + Serial.print("Master writing "); + Serial.println(x); + + MasterWire.beginTransmission(4); // transmit to device #4 + MasterWire.write("x is "); // sends five bytes + MasterWire.write(x); // sends one byte + MasterWire.endTransmission(); // stop transmitting + + x++; + #endif + delay(500); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +// Note that it is not advicable to call Serial.print() from within an ISR +void receiveEvent(int howMany){ + //Serial.print("Slave receving "); + while(1 < SlaveWire.available()){ // loop through all but the last + char c = SlaveWire.read(); // receive byte as a character + Serial.print(c); // print the character + } + int x = SlaveWire.read(); // receive byte as an integer + Serial.println(x); // print the integer +} + diff --git a/STM32F1/libraries/WireSlave/examples/selftest1/selftest1.ino b/STM32F1/libraries/WireSlave/examples/selftest1/selftest1.ino new file mode 100644 index 0000000..58f1e5c --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/selftest1/selftest1.ino @@ -0,0 +1,16 @@ +// Wire Slave Receiver +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + +// The code is temporarily moved to the code.cpp. +// This makes it possible to set breakpoints in eclipse IDE. +// I'm sure that there is an Eclipse configuration that makes it +// possible for it to detect .ino files as .cpp, but I'm lazy + diff --git a/STM32F1/libraries/WireSlave/examples/slave_receiver/slave_receiver.ino b/STM32F1/libraries/WireSlave/examples/slave_receiver/slave_receiver.ino new file mode 100644 index 0000000..bf9f255 --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/slave_receiver/slave_receiver.ino @@ -0,0 +1,36 @@ +// Wire Slave Receiver +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup(){ + Serial.begin(115200); // start serial for output + + Wire.begin(4); // join i2c bus with address #4 + Wire.onReceive(receiveEvent); // register event +} + +void loop(){ + delay(100); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +// Note that it is not advicable to call Serial.print() from within an ISR +void receiveEvent(int howMany){ + while(1 < Wire.available()){ // loop through all but the last + char c = Wire.read(); // receive byte as a character + Serial.print(c); // print the character + } + int x = Wire.read(); // receive byte as an integer + Serial.println(x); // print the integer +} diff --git a/STM32F1/libraries/WireSlave/examples/slave_sender/slave_sender.ino b/STM32F1/libraries/WireSlave/examples/slave_sender/slave_sender.ino new file mode 100644 index 0000000..75add4a --- /dev/null +++ b/STM32F1/libraries/WireSlave/examples/slave_sender/slave_sender.ino @@ -0,0 +1,32 @@ +// Wire Slave Sender +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Sends data as an I2C/TWI slave device +// Refer to the "Wire Master Reader" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(8); // join i2c bus with address #8 + Wire.onRequest(requestEvent); // register event +} + +void loop() +{ + delay(100); +} + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() +{ + Wire.write("hello "); // respond with message of 6 bytes + // as expected by master +} diff --git a/STM32F1/libraries/WireSlave/keywords.txt b/STM32F1/libraries/WireSlave/keywords.txt new file mode 100644 index 0000000..47ffd52 --- /dev/null +++ b/STM32F1/libraries/WireSlave/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +setClock KEYWORD2 +beginTransmission KEYWORD2 +endTransmission KEYWORD2 +requestFrom KEYWORD2 +onReceive KEYWORD2 +onRequest KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Wire KEYWORD2 +Wire1 KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/STM32F1/libraries/WireSlave/library.properties b/STM32F1/libraries/WireSlave/library.properties new file mode 100644 index 0000000..fd24ab1 --- /dev/null +++ b/STM32F1/libraries/WireSlave/library.properties @@ -0,0 +1,11 @@ +name=Wire_Slave +version=1.0 +author= +email= +sentence=Wire with slave support +paragraph=Experimental Wire with slave support +url= +architectures=STM32F1 +maintainer= +category=Communication +include=src/Wire_slave.h diff --git a/STM32F1/libraries/WireSlave/src/Wire.h b/STM32F1/libraries/WireSlave/src/Wire.h new file mode 100644 index 0000000..0a47d03 --- /dev/null +++ b/STM32F1/libraries/WireSlave/src/Wire.h @@ -0,0 +1,4 @@ +#pragma once +#include "Wire_slave.h" + +//#error "Something is trying to include Wire.h when Wire_slave.h is already included, they are mutually exclusive" diff --git a/STM32F1/libraries/WireSlave/src/Wire_slave.cpp b/STM32F1/libraries/WireSlave/src/Wire_slave.cpp new file mode 100644 index 0000000..5fb84f5 --- /dev/null +++ b/STM32F1/libraries/WireSlave/src/Wire_slave.cpp @@ -0,0 +1,524 @@ +/* + TwoWire.cpp - TWI/I2C library for Wiring & Arduino + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts + */ + +extern "C" { + #include + #include + #include +} + +#include "Wire_slave.h" +#include "wirish.h" +#include + +#define BUFFER_LENGTH 32 + +#define MASTER_ADDRESS 0x33 +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire(i2c_dev* i2cDevice) : + sel_hard(i2cDevice), + rxBuffer(nullptr), + rxBufferAllocated(0), + rxBufferIndex(0), + rxBufferLength(0), + txBuffer(nullptr), + txBufferAllocated(0), + txBufferIndex(0), + txBufferLength(0), + transmitting(false), + master(true), + dev_flags(0), + itc_msg(), + itc_slave_msg(), + user_onRequest(nullptr), + user_onReceive(nullptr) { +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(void) { + begin(MASTER_ADDRESS); +} + +void TwoWire::begin(uint8_t address){ + + rxBufferIndex = 0; + rxBufferLength = 0; + allocateRxBuffer(BUFFER_LENGTH); + + txBufferIndex = 0; + txBufferLength = 0; + allocateTxBuffer(BUFFER_LENGTH); + + transmitting = false; + + master = (address == MASTER_ADDRESS); + + // Set default speed to 100KHz + if (master) { + dev_flags = 0; + i2c_master_enable(sel_hard, dev_flags); + } else { + // TODO: I2C_SLAVE_DUAL_ADDRESS ? + dev_flags = I2C_SLAVE_GENERAL_CALL | I2C_SLAVE_USE_RX_BUFFER | + I2C_SLAVE_USE_TX_BUFFER; + + itc_slave_msg.addr = address; + itc_slave_msg.flags = 0; + itc_slave_msg.data = rxBuffer; + itc_slave_msg.length = 0; + itc_slave_msg.flags = 0; + + // TODO why does enable only work before setting IRS and address? + i2c_slave_enable(sel_hard, dev_flags); + + if (sel_hard==I2C1){ + // attach receive handler + i2c_slave_attach_recv_handler(sel_hard, &itc_slave_msg, onReceiveService1); + // attach transmit handler + i2c_slave_attach_transmit_handler(sel_hard, &itc_slave_msg, onRequestService1); + } + #if WIRE_INTERFACES_COUNT > 1 + else if (sel_hard==I2C2){ + // attach receive handler + i2c_slave_attach_recv_handler(sel_hard, &itc_slave_msg, onReceiveService2); + // attach transmit handler + i2c_slave_attach_transmit_handler(sel_hard, &itc_slave_msg, onRequestService2); + } + #endif + + i2c_slave_set_own_address(sel_hard, address); + } +} + +void TwoWire::begin(int address) { + begin((uint8_t) address); +} + +void TwoWire::end(void) { + free(txBuffer); + txBuffer = nullptr; + txBufferAllocated = 0; + free(rxBuffer); + rxBuffer = nullptr; + rxBufferAllocated = 0; + i2c_peripheral_disable(sel_hard); + i2c_master_release_bus(sel_hard); // TODO is this required? +} + +void TwoWire::setClock(uint32_t frequencyHz) { + switch (frequencyHz) { + case 400000: + dev_flags |= I2C_FAST_MODE; // set FAST_MODE bit + break; + case 100000: + default: + dev_flags &= ~I2C_FAST_MODE; // clear FAST_MODE bit + break; + } + if (sel_hard->regs->CR1 & I2C_CR1_PE){ + i2c_disable(sel_hard); + i2c_master_enable(sel_hard, dev_flags); + } +} + +uint8 TwoWire::process(bool stop) { + int8 res = i2c_master_xfer(sel_hard, &itc_msg, 1, 0); + + if (res == I2C_ERROR_PROTOCOL) { + if (sel_hard->error_flags & I2C_SR1_AF) { /* NACK */ + res = (sel_hard->error_flags & I2C_SR1_ADDR ? ENACKADDR : ENACKTRNS); + } else if (sel_hard->error_flags & I2C_SR1_OVR) { /* Over/Underrun */ + res = EDATA; + } else { /* Bus or Arbitration error */ + res = EOTHER; + } + i2c_disable(sel_hard); + i2c_master_enable(sel_hard, (I2C_BUS_RESET | dev_flags)); + } + + return res; +} + +//TODO: Add the ability to queue messages (adding a boolean to end of function +// call, allows for the Arduino style to stay while also giving the flexibility +// to bulk send +uint8 TwoWire::requestFrom(uint8_t address, uint8_t num_bytes, + uint32_t iaddress, uint8_t isize, uint8_t sendStop) { + + ASSERT(master); + + allocateRxBuffer(num_bytes); + // error if no memory block available to allocate the buffer + if (rxBuffer == nullptr) { + return EDATA; + } + + // reset tx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = 0; + + itc_msg.addr = address; + itc_msg.flags = I2C_MSG_READ; + itc_msg.length = num_bytes; + itc_msg.data = &rxBuffer[rxBufferIndex]; + process(sendStop); // TODO deal with to the return value + + // TODO handle iaddress & isize + rxBufferLength += itc_msg.xferred; + itc_msg.flags = 0; + + return rxBufferLength; +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, + uint8_t sendStop) { + // TODO shouldn't this set flag |= I2C_MSG_10BIT_ADDR ??? + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0, + (uint8_t) 0, sendStop); +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) { + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0, + (uint8_t) 0, (uint8_t) true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity) { + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0, + (uint8_t) 0, (uint8_t) true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) { + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0, + (uint8_t) 0, (bool) sendStop); +} + +void TwoWire::beginTransmission(uint8_t address) { + + // indicate that we are transmitting + transmitting = true; + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + itc_msg.addr = address; + itc_msg.data = &txBuffer[txBufferIndex]; + itc_msg.length = 0; + itc_msg.flags = 0; + +} + +void TwoWire::beginTransmission(int address) { + beginTransmission((uint8_t) address); +} + +// +// Originally, 'endTransmission' was an f(void) function. +// It has been modified to take one parameter indicating +// whether or not a STOP should be performed on the bus. +// Calling endTransmission(false) allows a sketch to +// perform a repeated start. +// +// WARNING: Nothing in the library keeps track of whether +// the bus tenure has been properly ended with a STOP. It +// is very possible to leave the bus in a hung state if +// no call to endTransmission(true) is made. Some I2C +// devices will behave oddly if they do not see a STOP. +// +uint8_t TwoWire::endTransmission(uint8_t sendStop) { + //UNUSED(sendStop); + int8_t ret = 4; + + if (master == true) { + + itc_msg.data = txBuffer; + itc_msg.length = txBufferLength; + itc_msg.flags = 0; + ret = process(sendStop); // Changed so that the return value from process is returned by this function see also the return line below + txBufferIndex = 0; + + // reset Tx buffer + resetTxBuffer(); // TODO why? isn't this just unesssesary? + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + // indicate that we are done transmitting + transmitting = false; + } + + return ret; +} + +// This provides backwards compatibility with the original +// definition, and expected behaviour, of endTransmission +// + +uint8_t TwoWire::endTransmission(void) { + return endTransmission(true); +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(uint8_t data) { + if (!transmitting && master) { + return 0; + } else { + // in master transmitter mode or slave tx event callback + allocateTxBuffer(txBufferLength + 1); + // error if no memory block available to allocate the buffer + if (txBuffer == nullptr) { + setWriteError(); + return 0; + } + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + // update amount in buffer + txBufferLength = txBufferIndex; + } + return 1; +} + +/** + * @brief This function must be called in slave Tx event callback or after + * beginTransmission() and before endTransmission(). + * @param pdata: pointer to the buffer data + * @param quantity: number of bytes to write + * @retval number of bytes ready to write. + */ +size_t TwoWire::write(const uint8_t *data, size_t quantity) { + if (!transmitting && master) { + return 0; + } else { + // in master transmitter mode or slave Tx event callback + allocateTxBuffer(txBufferLength + quantity); + // error if no memory block available to allocate the buffer + if (txBuffer == nullptr) { + setWriteError(); + return 0; + } + // put bytes in tx buffer + memcpy(&(txBuffer[txBufferIndex]), data, quantity); + txBufferIndex = txBufferIndex + quantity; + // update amount in buffer + txBufferLength = txBufferIndex; + return quantity; + } + return 0; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::available(void) { + return rxBufferLength - rxBufferIndex; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::read(void) { + int value = -1; + + // get each successive byte on each call + if (rxBufferIndex < rxBufferLength) { + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + + /* Commented as not I think it is not useful + * but kept to show that it is possible to + * reset rx buffer when no more data available */ + /*if(rxBufferIndex == rxBufferLength) { + resetRxBuffer(); + }*/ + } + + return value; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::peek(void) { + int value = -1; + + if (rxBufferIndex < rxBufferLength) { + value = rxBuffer[rxBufferIndex]; + } + + return value; +} + +void TwoWire::flush(void) { + rxBufferIndex = 0; + rxBufferLength = 0; + resetRxBuffer(); + txBufferIndex = 0; + txBufferLength = 0; + resetTxBuffer(); +} + +// behind the scenes function that is called when data is received +void __attribute__((always_inline)) TwoWire::onReceiveService(i2c_msg* msg) { + // don't bother if user hasn't registered a callback + if (!user_onReceive) { + return; + } + + // don't bother if rx buffer is in use by a master requestFrom() op + // i know this drops data, but it allows for slight stupidity + // meaning, they may not have read all the master requestFrom() data yet + if (rxBufferIndex < rxBufferLength) { + return; + } + // copy twi rx buffer into local read buffer + // this enables new reads to happen in parallel + // + // TODO: Something is strange here, isn't msg->data==rxBuffer? nope, itsnot + // + memcpy(rxBuffer, msg->data, msg->length); + // set rx iterator vars + rxBufferIndex = 0; + rxBufferLength = msg->length; + // alert user program + user_onReceive(msg->length); +} + +// behind the scenes function that is called when data is requested +void __attribute__((always_inline)) TwoWire::onRequestService(i2c_msg* msg) { + // don't bother if user hasn't registered a callback + if (!user_onRequest) { + return; + } + + // reset tx buffer iterator vars + // !!! this will kill any pending pre-master sendTo() activity + txBufferIndex = 0; + txBufferLength = 0; + // alert user program + user_onRequest(); + + // update i2c_msg + msg->data = txBuffer; + msg->length = txBufferLength; + msg->xferred = 0; +} + +// sets function called on slave write +void TwoWire::onReceive(void (*function)(int)) { + user_onReceive = function; +} + +// sets function called on slave read +void TwoWire::onRequest(void (*function)(void)) { + user_onRequest = function; +} + +/** + * @brief Allocate the Rx/Tx buffer to the requested length if needed + * @note Minimum allocated size is BUFFER_LENGTH) + * @param length: number of bytes to allocate + */ +inline void TwoWire::allocateRxBuffer(size_t length) { + // By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer. + if (length < BUFFER_LENGTH) { + length = BUFFER_LENGTH; + } + if (rxBufferAllocated < length) { + rxBuffer = (uint8_t *) realloc(rxBuffer, length * sizeof(uint8_t)); + rxBufferAllocated = (rxBuffer != nullptr) ? length : 0; + } +} + +inline void TwoWire::allocateTxBuffer(size_t length) { + // By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer. + if (length < BUFFER_LENGTH) { + length = BUFFER_LENGTH; + } + if (txBufferAllocated < length) { + txBuffer = (uint8_t *) realloc(txBuffer, length * sizeof(uint8_t)); + txBufferAllocated = (txBuffer != nullptr) ? length : 0; + } +} + +/** + * @brief Reset Rx/Tx buffer content to 0 + */ +inline void TwoWire::resetRxBuffer(void) { + if (rxBuffer != nullptr) + memset(rxBuffer, 0, rxBufferAllocated); +} + +inline void TwoWire::resetTxBuffer(void) { + if (txBuffer != nullptr) + memset(txBuffer, 0, txBufferAllocated); +} + + +// Preinstantiate Objects ////////////////////////////////////////////////////// +TwoWire& Wire = TwoWire::getInstance(); //SCL:D14 SDA:D15 +#if WIRE_INTERFACES_COUNT > 1 +TwoWire& Wire1 = TwoWire::getInstance1(); //SCL: D1 SDA: D0 +#endif + +// Static methods ////////////////////////////////////////////////////////////// + +TwoWire& TwoWire::getInstance(){ + static TwoWire* instance = nullptr; + if (!instance) { + instance = new TwoWire(I2C1); + } + return *instance; +} + +#if WIRE_INTERFACES_COUNT > 1 +TwoWire& TwoWire::getInstance1(){ + static TwoWire* instance = nullptr; + if (!instance) { + instance = new TwoWire(I2C2); + } + return *instance; +} +#endif + +// onRequestServiceX and onReceiveServiceX can't be inline since they +// are exclusively called via a function pointer +void TwoWire::onRequestService1(i2c_msg* msg) { + Wire.onRequestService(msg); +} + +void TwoWire::onReceiveService1(i2c_msg* msg) { + Wire.onReceiveService(msg); +} + +#if WIRE_INTERFACES_COUNT > 1 +void TwoWire::onRequestService2(i2c_msg* msg) { + Wire1.onRequestService(msg); +} +void TwoWire::onReceiveService2(i2c_msg* msg) { + Wire1.onReceiveService(msg); +} +#endif diff --git a/STM32F1/libraries/WireSlave/src/Wire_slave.h b/STM32F1/libraries/WireSlave/src/Wire_slave.h new file mode 100644 index 0000000..a99ab41 --- /dev/null +++ b/STM32F1/libraries/WireSlave/src/Wire_slave.h @@ -0,0 +1,151 @@ +/* + TwoWire.h - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts + */ + +#ifndef TwoWire_h +#define TwoWire_h + +#include +#include "Stream.h" +#include "Arduino.h" +#include + + +// WIRE_HAS_END means Wire has end() +#ifndef WIRE_HAS_END +#define WIRE_HAS_END 1 +#endif + +#ifndef WIRE_INTERFACES_COUNT +#define WIRE_INTERFACES_COUNT 2 +#endif + +/* return codes from endTransmission() */ +typedef enum EndTranmissionCodes { + SUCCESS = 0, /* transmission was successful */ + EDATA = 1, /* too much data */ + ENACKADDR = 2, /* received nack on transmit of address */ + ENACKTRNS = 3, /* received nack on transmit of data */ + EOTHER = 4, /* other error */ +} EndTranmissionCodes; + +class TwoWire: public Stream { +private: + i2c_dev* sel_hard; + + uint8_t *rxBuffer; // lazy allocation + uint8_t rxBufferAllocated; + uint8_t rxBufferIndex; + uint8_t rxBufferLength; + + uint8_t *txBuffer; // lazy allocation + uint8_t txBufferAllocated; + uint8_t txBufferIndex; + uint8_t txBufferLength; + + bool transmitting; + + bool master; + + uint8 dev_flags; + i2c_msg itc_msg; + i2c_msg itc_slave_msg; + + void (*user_onRequest)(void); + void (*user_onReceive)(int quantity); + + void allocateRxBuffer(size_t length); + void allocateTxBuffer(size_t length); + + void resetRxBuffer(void); + void resetTxBuffer(void); + uint8 process(bool stop = true); // wrapper for i2c_master_xfer + + inline void __attribute__((always_inline)) onReceiveService(i2c_msg* msg); + inline void __attribute__((always_inline)) onRequestService(i2c_msg* msg); + + static void onRequestService1(i2c_msg*); + static void onReceiveService1(i2c_msg*); + #if WIRE_INTERFACES_COUNT > 1 + static void onRequestService2(i2c_msg*); + static void onReceiveService2(i2c_msg*); + #endif + + TwoWire(i2c_dev* i2cDevice); + TwoWire() = delete; + TwoWire(const TwoWire&) = delete; + TwoWire& operator=(const TwoWire&) = delete; + TwoWire(TwoWire&&) = delete; + TwoWire& operator=(TwoWire&&) = delete; + +public: + // return the 'Wire' instance (using I2C1) + static TwoWire& getInstance(); + #if WIRE_INTERFACES_COUNT > 1 + // return the 'Wire1' instance (using I2C2) + static TwoWire& getInstance1(); + #endif + + void begin(); // master mode + void begin(uint8_t myAddress); //slave mode + void begin(int myAddress); //slave mode + void end(); + void setClock(uint32_t frequencyHz); + void beginTransmission(uint8_t slaveAddress); + void beginTransmission(int slaveAddress); + uint8_t endTransmission(void); + uint8_t endTransmission(uint8_t sendStop); + + uint8_t requestFrom(uint8_t slaveAddress, uint8_t quantity); + uint8_t requestFrom(uint8_t slaveAddress, uint8_t quantity, uint8_t sendStop); + uint8_t requestFrom(uint8_t slaveAddress, uint8_t num_bytes, uint32_t iaddress, uint8_t isize, uint8_t sendStop); + uint8_t requestFrom(int slaveAddress, int quantity); + uint8_t requestFrom(int slaveAddress, int quantity, int sendStop); + + virtual size_t write(uint8_t data); + virtual size_t write(const uint8_t *data, size_t quantity); + virtual int available(void); + virtual int read(void); + virtual int peek(void); + virtual void flush(void); + void onReceive(void (*)(int quantity)); + void onRequest(void (*)(void)); + + inline size_t write(unsigned long data) { + return write((uint8_t) data); + } + inline size_t write(long data) { + return write((uint8_t) data); + } + inline size_t write(unsigned int data) { + return write((uint8_t) data); + } + inline size_t write(int data) { + return write((uint8_t) data); + } + using Print::write; +}; + +extern TwoWire& Wire; +#if WIRE_INTERFACES_COUNT > 1 +extern TwoWire& Wire1; +#endif + +#endif // TwoWire_h diff --git a/STM32F1/libraries/WireSlave/src/Wire_slave.h.gch b/STM32F1/libraries/WireSlave/src/Wire_slave.h.gch new file mode 100644 index 0000000..5a63450 Binary files /dev/null and b/STM32F1/libraries/WireSlave/src/Wire_slave.h.gch differ diff --git a/STM32F1/libraries/WireSlave/src/i2c_slave.c b/STM32F1/libraries/WireSlave/src/i2c_slave.c new file mode 100644 index 0000000..82ade9a --- /dev/null +++ b/STM32F1/libraries/WireSlave/src/i2c_slave.c @@ -0,0 +1,795 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/i2c.c + * @author Perry Hung + * @author Barry Carter + * @brief Inter-Integrated Circuit (I2C) support. + * + * Master and Slave supported + * I2C slave support added 2012 by Barry Carter. barry.carter@gmail.com, headfuzz.co.uk + */ + +#include "libmaple/i2c_common_slave.h" + +#include "i2c_private.h" + + +#include "libmaple/i2c_slave.h" +#include +#include +#include +#include +#include + +#include + +static inline int32 wait_for_state_change(i2c_dev *dev, + i2c_state state, + uint32 timeout); +static void set_ccr_trise(i2c_dev *dev, uint32 flags); + +/** + * @brief Fill data register with slave address + * @param dev I2C device + * @param addr Slave address + * @param rw Read/write bit + */ +static inline void i2c_send_slave_addr(i2c_dev *dev, uint32 addr, uint32 rw) { + dev->regs->DR = (addr << 1) | rw; +} + +/* + * Simple debugging trail. Define I2C_DEBUG to turn on. + */ +#ifdef I2C_DEBUG + +#define NR_CRUMBS 128 +struct crumb { + uint32 event; + uint32 arg0; + uint32 arg1; + uint32 arg2; // filler to make the data fit GDB memory dump screen +}; +static struct crumb crumbs[NR_CRUMBS]; +static uint32 cur_crumb = 0; + +static inline void i2c_drop_crumb(uint32 event, uint32 arg0, uint32 arg1) { + if (cur_crumb < NR_CRUMBS) { + struct crumb *crumb = &crumbs[cur_crumb++]; + crumb->event = event; + crumb->arg0 = arg0; + crumb->arg1 = arg1; + crumb->arg2 = cur_crumb-1; + } +} +#define I2C_CRUMB(event, arg0, arg1) i2c_drop_crumb(event, arg0, arg1) + +#else +#define I2C_CRUMB(event, arg0, arg1) +#endif + +enum { + IRQ_ENTRY = 1, + TXE_ONLY = 2, + TXE_BTF = 3, + STOP_SENT = 4, + TEST = 5, + RX_ADDR_START = 6, + RX_ADDR_STOP = 7, + RXNE_ONLY = 8, + RXNE_SENDING = 9, + RXNE_START_SENT = 10, + RXNE_STOP_SENT = 11, + RXNE_DONE = 12, + ERROR_ENTRY = 13, +}; + +/** + * @brief Reset an I2C bus. + * + * Reset is accomplished by clocking out pulses until any hung slaves + * release SDA and SCL, then generating a START condition, then a STOP + * condition. + * + * @param dev I2C device + */ +void i2c_bus_reset(const i2c_dev *dev) { + /* Release both lines */ + i2c_master_release_bus(dev); + + /* + * Make sure the bus is free by clocking it until any slaves release the + * bus. + */ + while (!gpio_read_bit(sda_port(dev), dev->sda_pin)) { + /* Wait for any clock stretching to finish */ + while (!gpio_read_bit(scl_port(dev), dev->scl_pin)) + ; + delay_us(10); + + /* Pull low */ + gpio_write_bit(scl_port(dev), dev->scl_pin, 0); + delay_us(10); + + /* Release high again */ + gpio_write_bit(scl_port(dev), dev->scl_pin, 1); + delay_us(10); + } + + /* Generate start then stop condition */ + gpio_write_bit(sda_port(dev), dev->sda_pin, 0); + delay_us(10); + gpio_write_bit(scl_port(dev), dev->scl_pin, 0); + delay_us(10); + gpio_write_bit(scl_port(dev), dev->scl_pin, 1); + delay_us(10); + gpio_write_bit(sda_port(dev), dev->sda_pin, 1); +} + +/** + * @brief Initialize an I2C device and reset its registers to their + * default values. + * @param dev Device to initialize. + */ +void i2c_init(i2c_dev *dev) { + + rcc_reset_dev(dev->clk_id); + rcc_clk_enable(dev->clk_id); + _i2c_irq_priority_fixup(dev); +} + +/* Hack for deprecated bit of STM32F1 functionality */ +#ifndef _I2C_HAVE_DEPRECATED_I2C_REMAP +#define _i2c_handle_remap(dev, flags) ((void)0) +#endif + +/** + * @brief Initialize an I2C device as bus master + * @param dev Device to enable + * @param flags Bitwise or of the following I2C options: + * I2C_FAST_MODE: 400 khz operation, + * I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for + * fast mode), + * I2C_BUS_RESET: Reset the bus and clock out any hung slaves on + * initialization, + * I2C_10BIT_ADDRESSING: Enable 10-bit addressing, + * I2C_REMAP: (deprecated, STM32F1 only) Remap I2C1 to SCL/PB8 + * SDA/PB9. + */ +void i2c_master_enable(i2c_dev *dev, uint32 flags) { + /* PE must be disabled to configure the device */ + ASSERT(!(dev->regs->CR1 & I2C_CR1_PE)); + + /* Ugh */ + _i2c_handle_remap(dev, flags); + + /* Reset the bus. Clock out any hung slaves. */ + if (flags & I2C_BUS_RESET) { + i2c_bus_reset(dev); + } + + /* Turn on clock and set GPIO modes */ + i2c_init(dev); + i2c_config_gpios(dev); + + /* Configure clock and rise time, but only if in master mode */ + if (!(flags & (I2C_SLAVE_DUAL_ADDRESS|I2C_SLAVE_GENERAL_CALL))) { + set_ccr_trise(dev, flags); + } + + /* Enable event and buffer interrupts */ + nvic_irq_enable(dev->ev_nvic_line); + nvic_irq_enable(dev->er_nvic_line); + i2c_enable_irq(dev, I2C_IRQ_EVENT | I2C_IRQ_BUFFER | I2C_IRQ_ERROR); + + /* Configure the slave unit */ + if (flags & I2C_SLAVE_DUAL_ADDRESS) { + i2c_slave_dual_address_enable(dev); + } + + if (flags & I2C_SLAVE_GENERAL_CALL) { + i2c_slave_general_call_enable(dev); + } + + /* store all of the flags */ + dev->config_flags = flags; + + /* Make it go! */ + i2c_peripheral_enable(dev); + i2c_enable_ack(dev); + + dev->state = I2C_STATE_IDLE; +} + +/** + * @brief Initialize an I2C device as slave (and master) + * @param dev Device to enable + * @param flags Bitwise or of the following I2C options: + * I2C_FAST_MODE: 400 khz operation, + * I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for + * fast mode), + * I2C_BUS_RESET: Reset the bus and clock out any hung slaves on + * initialization, + * I2C_10BIT_ADDRESSING: Enable 10-bit addressing, + * I2C_REMAP: (deprecated, STM32F1 only) Remap I2C1 to SCL/PB8 + * SDA/PB9. + * I2C_SLAVE_DUAL_ADDRESS: Slave can respond on 2 i2C addresses + * I2C_SLAVE_GENERAL_CALL: SLA+W broadcast to all general call + * listeners on bus. Addr 0x00 + * I2C_SLAVE_USE_RX_BUFFER: Use a buffer to receive the incoming + * data. Callback at end of recv + * I2C_SLAVE_USE_TX_BUFFER: Use a buffer to transmit data. + * Callback will be called before tx + */ +void i2c_slave_enable(i2c_dev *dev, uint32 flags) { + // TODO: Figure out why i2c_disable(I2C2) causes a crash when I2C1 is enabled + i2c_disable(dev); + i2c_master_enable(dev, flags); +} + +/** + * @brief Process an i2c transaction. + * + * Transactions are composed of one or more i2c_msg's, and may be read + * or write tranfers. Multiple i2c_msg's will generate a repeated + * start in between messages. + * + * @param dev I2C device + * @param msgs Messages to send/receive + * @param num Number of messages to send/receive + * @param timeout Bus idle timeout in milliseconds before aborting the + * transfer. 0 denotes no timeout. + * @return 0 on success, + * I2C_ERROR_PROTOCOL if there was a protocol error, + * I2C_ERROR_TIMEOUT if the transfer timed out. + */ +int32 i2c_master_xfer(i2c_dev *dev, + i2c_msg *msgs, + uint16 num, + uint32 timeout) { + int32 rc; + + ASSERT(dev->state == I2C_STATE_IDLE); + + dev->msg = msgs; + dev->msgs_left = num; + dev->timestamp = systick_uptime(); + dev->state = I2C_STATE_BUSY; + + i2c_enable_irq(dev, I2C_IRQ_EVENT); + i2c_start_condition(dev); + + rc = wait_for_state_change(dev, I2C_STATE_XFER_DONE, timeout); + if (rc < 0) { + goto out; + } + + dev->state = I2C_STATE_IDLE; +out: + return rc; +} + +/** + * @brief Wait for an I2C event, or time out in case of error. + * @param dev I2C device + * @param state I2C_state state to wait for + * @param timeout Timeout, in milliseconds + * @return 0 if target state is reached, a negative value on error. + */ +static inline int32 wait_for_state_change(i2c_dev *dev, + i2c_state state, + uint32 timeout) { + i2c_state tmp; + + while (1) { + tmp = dev->state; + + if (tmp == I2C_STATE_ERROR) { + return I2C_STATE_ERROR; + } + + if (tmp == state) { + return 0; + } + + if (timeout) { + if (systick_uptime() > (dev->timestamp + timeout)) { + /* TODO: overflow? */ + /* TODO: racy? */ + return I2C_ERROR_TIMEOUT; + } + } + } +} + +/* + * Private API + */ + +/* + * IRQ handler for I2C master and slave. + * Handles transmission/reception. + */ +void _i2c_irq_handler(i2c_dev *dev) { + /* WTFs: + * - Where is I2C_MSG_10BIT_ADDR handled? + */ + i2c_msg *msg = dev->msg; + + uint8 read = msg->flags & I2C_MSG_READ; + + uint32 sr1 = dev->regs->SR1; + uint32 sr2 = dev->regs->SR2; + I2C_CRUMB(IRQ_ENTRY, sr1, sr2); + + /* + * Reset timeout counter + */ + dev->timestamp = systick_uptime(); + + /* + * Add Slave support + */ + + /* Check to see if in slave mode */ + if (dev->config_flags&(I2C_SLAVE_DUAL_ADDRESS|I2C_SLAVE_GENERAL_CALL)) { + + /* Check for address match */ + if (sr1 & I2C_SR1_ADDR) { + /* Find out which address was matched */ + /* Check the general call address first */ + if (sr2 & I2C_SR2_GENCALL) { + dev->i2c_slave_msg->addr = 0; + } + /* We matched the secondary address */ + else if (sr2 & I2C_SR2_DUALF) { + dev->i2c_slave_msg->addr = dev->regs->OAR2 & 0xFE; + } + /* We matched the primary address */ + else if ((sr2 & I2C_SR2_DUALF) != I2C_SR2_DUALF) { + dev->i2c_slave_msg->addr = dev->regs->OAR1 & 0xFE; + } + /* Shouldn't get here */ + else { + dev->i2c_slave_msg->addr = -1; /* uh oh */ + } + + /* if we have buffered io */ + if ((dev->config_flags & I2C_SLAVE_USE_RX_BUFFER) || + (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER)) { + + /* if receiving then this would be a repeated start + * + *if we have some bytes already + */ + if ((dev->state == I2C_STATE_SL_RX) && + (dev->i2c_slave_msg->xferred > 0) && + (dev->config_flags & I2C_SLAVE_USE_RX_BUFFER)) { + /* Call the callback with the contents of the data */ + if (dev->i2c_slave_recv_callback != NULL) { + (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); + } + } + + /* Reset the message back to defaults. + * We are starting a new message + */ + dev->i2c_slave_msg->flags = 0; + dev->i2c_slave_msg->length = 0; + dev->i2c_slave_msg->xferred = 0; + dev->msgs_left = 0; + dev->timestamp = systick_uptime(); + + /* We have been addressed with SLA+R so + * the master wants us to transmit + */ + if ((sr1 & I2C_SR1_TXE) && + (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER)) { + /* Call the transmit callback so it can populate the msg + * data with the bytes to go + */ + if (dev->i2c_slave_transmit_callback != NULL) { + (*(dev->i2c_slave_transmit_callback))(dev->i2c_slave_msg); + } + } + dev->state = I2C_STATE_BUSY; + } + + sr1 = sr2 = 0; + } + + /* EV3: Master requesting data from slave. Transmit a byte*/ + if (sr1 & I2C_SR1_TXE) { + if (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER) { + if (dev->i2c_slave_msg->xferred >= dev->i2c_slave_msg->length) { + /* End of the transmit buffer? If so we NACK */ + i2c_disable_ack(dev); + /* We have to either issue a STOP or write something here. + * STOP here seems to screw up some masters, + * For now padding with 0 + */ + i2c_write(dev, 0); + /*i2c_stop_condition(dev); // This is causing bus lockups way more than it should !? Seems some I2C master devices freak out here*/ + } + else + { + /* NACk the last byte */ + if (dev->i2c_slave_msg->xferred == dev->i2c_slave_msg->length-1) { + i2c_disable_ack(dev); + } + else { + i2c_enable_ack(dev); + } + i2c_write(dev, dev->i2c_slave_msg->data[dev->i2c_slave_msg->xferred++]); + } + } + else + { + /* Call the callback to get the data we need. + * The callback is expected to write using i2c_write(...) + * If the slave is going to terminate the transfer, this function should + * also do a NACK on the last byte! + */ + if (dev->i2c_slave_transmit_callback != NULL) (*(dev->i2c_slave_transmit_callback))(dev->i2c_slave_msg); + } + + dev->state = I2C_STATE_BUSY; + sr1 = sr2 = 0; + } + + /* EV2: Slave received data from a master. Get from DR */ + if (sr1 & I2C_SR1_RXNE) { + if (dev->config_flags & I2C_SLAVE_USE_RX_BUFFER) { + /* Fill the buffer with the contents of the data register */ + /* These is potential for buffer overflow here, so we should + * really store the size of the array. This is expensive in + * the ISR so left out for now. We must trust the implementor! + */ + dev->i2c_slave_msg->data[dev->i2c_slave_msg->xferred++] = dev->regs->DR; + dev->i2c_slave_msg->length++; + } + else { + /* Call the callback with the contents of the data */ + dev->i2c_slave_msg->data[0] = dev->regs->DR; + if (dev->i2c_slave_recv_callback != NULL) (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); + } + dev->state = I2C_STATE_SL_RX; + sr1 = sr2 = 0; + } + + /* EV4: Slave has detected a STOP condition on the bus */ + if (sr1 & I2C_SR1_STOPF) { + dev->regs->CR1 |= I2C_CR1_PE; + + if ((dev->config_flags & I2C_SLAVE_USE_RX_BUFFER) || + (dev->config_flags & I2C_SLAVE_USE_TX_BUFFER)) { + + /* The callback with the data will happen on a NACK of the last data byte. + * This is handled in the error IRQ (AF bit) + */ + /* Handle the case where the master misbehaves by sending no NACK */ + if (dev->state != I2C_STATE_IDLE) { + if (dev->state == I2C_STATE_SL_RX) { + if (dev->i2c_slave_recv_callback != NULL) (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); + } + else { + if (dev->i2c_slave_transmit_callback != NULL) (*(dev->i2c_slave_transmit_callback))(dev->i2c_slave_msg); + } + } + } + + sr1 = sr2 = 0; + dev->state = I2C_STATE_IDLE; + } + + return; + } + + /* + * EV5: Start condition sent + */ + if (sr1 & I2C_SR1_SB) { + msg->xferred = 0; + i2c_enable_irq(dev, I2C_IRQ_BUFFER); + + /* + * Master receiver + */ + if (read) { + i2c_enable_ack(dev); + } + + i2c_send_slave_addr(dev, msg->addr, read); + sr1 = sr2 = 0; + } + + /* + * EV6: Slave address sent + */ + if (sr1 & I2C_SR1_ADDR) { + /* + * Special case event EV6_1 for master receiver. + * Generate NACK and restart/stop condition after ADDR + * is cleared. + */ + if (read) { + if (msg->length == 1) { + i2c_disable_ack(dev); + if (dev->msgs_left > 1) { + i2c_start_condition(dev); + I2C_CRUMB(RX_ADDR_START, 0, 0); + } else { + i2c_stop_condition(dev); + I2C_CRUMB(RX_ADDR_STOP, 0, 0); + } + } + } else { + /* + * Master transmitter: write first byte to fill shift + * register. We should get another TXE interrupt + * immediately to fill DR again. + */ + if (msg->length > 1) { + i2c_write(dev, msg->data[msg->xferred++]); + } else if (msg->length == 0) { /* We're just sending an address */ + i2c_stop_condition(dev); + /* + * Turn off event interrupts to keep BTF from firing until + * the end of the stop condition. Why on earth they didn't + * have a start/stop condition request clear BTF is beyond + * me. + */ + i2c_disable_irq(dev, I2C_IRQ_EVENT); + I2C_CRUMB(STOP_SENT, 0, 0); + dev->state = I2C_STATE_XFER_DONE; + } /* else we're just sending one byte */ + } + sr1 = sr2 = 0; + } + + /* + * EV8: Master transmitter + * Transmit buffer empty, but we haven't finished transmitting the last + * byte written. + */ + if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) { + I2C_CRUMB(TXE_ONLY, 0, 0); + if (dev->msgs_left) { + i2c_write(dev, msg->data[msg->xferred++]); + if (msg->xferred == msg->length) { + /* + * End of this message. Turn off TXE/RXNE and wait for + * BTF to send repeated start or stop condition. + */ + i2c_disable_irq(dev, I2C_IRQ_BUFFER); + dev->msgs_left--; + } + } else { + /* + * This should be impossible... + */ + ASSERT(0); + } + sr1 = sr2 = 0; + } + + /* + * EV8_2: Master transmitter + * Last byte sent, program repeated start/stop + */ + if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) { + I2C_CRUMB(TXE_BTF, 0, 0); + if (dev->msgs_left) { + I2C_CRUMB(TEST, 0, 0); + /* + * Repeated start insanity: We can't disable ITEVTEN or else SB + * won't interrupt, but if we don't disable ITEVTEN, BTF will + * continually interrupt us. What the fuck ST? + */ + i2c_start_condition(dev); + while (!(dev->regs->SR1 & I2C_SR1_SB)) + ; + dev->msg++; + } else { + i2c_stop_condition(dev); + + /* + * Turn off event interrupts to keep BTF from firing until + * the end of the stop condition. Why on earth they didn't + * have a start/stop condition request clear BTF is beyond + * me. + */ + i2c_disable_irq(dev, I2C_IRQ_EVENT); + I2C_CRUMB(STOP_SENT, 0, 0); + dev->state = I2C_STATE_XFER_DONE; + } + sr1 = sr2 = 0; + } + + /* + * EV7: Master Receiver + */ + if (sr1 & I2C_SR1_RXNE) { + I2C_CRUMB(RXNE_ONLY, 0, 0); + msg->data[msg->xferred++] = dev->regs->DR; + + /* + * EV7_1: Second to last byte in the reception? Set NACK and generate + * stop/restart condition in time for the last byte. We'll get one more + * RXNE interrupt before shutting things down. + */ + if (msg->xferred == (msg->length - 1)) { + i2c_disable_ack(dev); + if (dev->msgs_left > 2) { + i2c_start_condition(dev); + I2C_CRUMB(RXNE_START_SENT, 0, 0); + } else { + i2c_stop_condition(dev); + I2C_CRUMB(RXNE_STOP_SENT, 0, 0); + } + } else if (msg->xferred == msg->length) { + dev->msgs_left--; + if (dev->msgs_left == 0) { + /* + * We're done. + */ + I2C_CRUMB(RXNE_DONE, 0, 0); + dev->state = I2C_STATE_XFER_DONE; + } else { + dev->msg++; + } + } + } +} + +/* + * Interrupt handler for I2C error conditions. Aborts any pending I2C + * transactions. + */ +void _i2c_irq_error_handler(i2c_dev *dev) { + I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2); + + dev->error_flags = dev->regs->SR1 & (I2C_SR1_BERR | + I2C_SR1_ARLO | + I2C_SR1_AF | + I2C_SR1_OVR); + + /* Are we in slave mode? */ + if (dev->config_flags & (I2C_SLAVE_DUAL_ADDRESS|I2C_SLAVE_GENERAL_CALL)) { + /* Check to see if the master device did a NAK on the last bit + * This is perfectly valid for a master to do this on the bus. + * We ignore this. Any further error processing takes us into dead + * loop waiting for the stop condition that will never arrive + */ + if (dev->regs->SR1 & I2C_SR1_AF) { + /* Clear flags */ + dev->regs->SR1 = 0; + dev->regs->SR2 = 0; + /* We need to write something to CR1 to clear the flag. + * This isn't really mentioned but seems important */ + i2c_enable_ack(dev); + + if (dev->state == I2C_STATE_SL_RX && + dev->config_flags & I2C_SLAVE_USE_RX_BUFFER && + dev->i2c_slave_msg->xferred > 0) { + /* Call the callback with the contents of the data */ + if (dev->i2c_slave_recv_callback != NULL) (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); + } + + dev->state = I2C_STATE_IDLE; + return; + } + /* Catch any other strange errors while in slave mode. + * I have seen BERR caused by an over fast master device + * as well as several overflows and arbitration failures. + * We are going to reset SR flags and carry on at this point which + * is not the best thing to do, but stops the bus locking up completely + * If we carry on below and send the stop bit, the code spins forever */ + /* Clear flags */ + dev->regs->SR1 = 0; + dev->regs->SR2 = 0; + dev->state = I2C_STATE_IDLE; + return; + } + + /* Clear flags */ + dev->regs->SR1 = 0; + dev->regs->SR2 = 0; + + i2c_stop_condition(dev); + i2c_disable_irq(dev, I2C_IRQ_BUFFER | I2C_IRQ_EVENT | I2C_IRQ_ERROR); + dev->state = I2C_STATE_ERROR; +} + +/* + * CCR/TRISE configuration helper + */ +static void set_ccr_trise(i2c_dev *dev, uint32 flags) { + uint32 ccr = 0; + uint32 trise = 0; + uint32 clk_mhz = _i2c_bus_clk(dev); + uint32 clk_hz = clk_mhz * (1000 * 1000); + + i2c_set_input_clk(dev, clk_mhz); + + if (flags & I2C_FAST_MODE) { + ccr |= I2C_CCR_FS; + + if (flags & I2C_DUTY_16_9) { + /* Tlow/Thigh = 16/9 */ + ccr |= I2C_CCR_DUTY_16_9; + ccr |= clk_hz / (400000 * 25); + } else { + /* Tlow/Thigh = 2 */ + ccr |= clk_hz / (400000 * 3); + } + + trise = (300 * clk_mhz / 1000) + 1; + } else { + /* Tlow/Thigh = 1 */ + ccr = clk_hz / (100000 * 2); + trise = clk_mhz + 1; + } + + /* Set minimum required value if CCR < 1*/ + if ((ccr & I2C_CCR_CCR) == 0) { + ccr |= 0x1; + } + + i2c_set_clk_control(dev, ccr); + i2c_set_trise(dev, trise); +} + + +/** + * @brief callback for when the device acts as a slave. If using an rx buffer, this is triggered + * after the last byte, otherwise it is called for every incoming packet. + * @param dev I2C device + * @param msg The dev_msg to pass to the slave init code + * @param func The function pointer to call + */ +void i2c_slave_attach_recv_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_recv_callback_func func) { + dev->i2c_slave_recv_callback = func; + dev->i2c_slave_msg = msg; + msg->xferred = 0; +} + + +/** + * @brief callback for when the device acts as a slave. If using a tx buffer, this is triggered + * after the device is successsfully addressed with SLA+R. + * @param dev I2C device + * @param msg The dev_msg to pass to the slave init code + * @param func The function pointer to call + */ +void i2c_slave_attach_transmit_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_transmit_callback_func func) { + dev->i2c_slave_transmit_callback = func; + dev->i2c_slave_msg = msg; + msg->xferred = 0; +} diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/i2c_common.h b/STM32F1/libraries/WireSlave/src/libmaple/i2c_common_slave.h similarity index 82% rename from STM32F3/cores/maple/libmaple/include/libmaple/i2c_common.h rename to STM32F1/libraries/WireSlave/src/libmaple/i2c_common_slave.h index 17cabe3..605c663 100644 --- a/STM32F3/cores/maple/libmaple/include/libmaple/i2c_common.h +++ b/STM32F1/libraries/WireSlave/src/libmaple/i2c_common_slave.h @@ -33,6 +33,9 @@ * CONTENTS UNSTABLE. The existence of this file is an implementation * detail. Never include it directly. If you need something from * here, include instead. + * + * I2C slave support added 2012 by Barry Carter. barry.carter@gmail.com, headfuzz.co.uk + * */ #ifndef _LIBMAPLE_I2C_COMMON_H_ @@ -52,9 +55,12 @@ typedef enum i2c_state { I2C_STATE_IDLE = 1, /**< Idle */ I2C_STATE_XFER_DONE = 2, /**< Done with transfer */ I2C_STATE_BUSY = 3, /**< Busy */ + I2C_STATE_SL_RX = 4, /**< Slave receiving */ I2C_STATE_ERROR = -1 /**< Error occurred */ } i2c_state; +typedef void (*i2c_slave_recv_callback_func)(struct i2c_msg *); +typedef void (*i2c_slave_transmit_callback_func)(struct i2c_msg *); /** * @brief I2C device type. */ @@ -88,6 +94,17 @@ typedef struct i2c_dev { nvic_irq_num ev_nvic_line; /**< Event IRQ number */ nvic_irq_num er_nvic_line; /**< Error IRQ number */ volatile i2c_state state; /**< Device state */ + uint32 config_flags; /**< Configuration flags */ + + /* + * Slave implementation. Callback functions in this struct allow + * for a separate callback function for each I2C unit available onboard + */ + i2c_slave_transmit_callback_func i2c_slave_transmit_callback; + i2c_slave_recv_callback_func i2c_slave_recv_callback; + + struct i2c_msg *i2c_slave_msg; /* the message that the i2c slave will use */ + } i2c_dev; #endif diff --git a/STM32F1/libraries/WireSlave/src/libmaple/i2c_slave.h b/STM32F1/libraries/WireSlave/src/libmaple/i2c_slave.h new file mode 100644 index 0000000..cdc3858 --- /dev/null +++ b/STM32F1/libraries/WireSlave/src/libmaple/i2c_slave.h @@ -0,0 +1,475 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/i2c.h + * @brief Inter-Integrated Circuit (I2C) peripheral support + * + * Supports Master and Slave. + * Master Usage notes: + * + * - Enable an I2C device with i2c_master_enable(). + * - Initialize an array of struct i2c_msg to suit the bus + * transactions (reads/writes) you wish to perform. + * - Call i2c_master_xfer() to do the work. + * + * Slave Usage notes: + * - Enable I2C slave by calling i2c_slave_enable(). + * Check flags for usage. Enabling master also enabled slave. + * - initialise the i2c_msg struct and the data buffer + * - initialise the callback functions + * + * I2C slave support added 2012 by Barry Carter. barry.carter@gmail.com, headfuzz.co.uk + */ + +#ifndef _LIBMAPLE_I2C_H_ +#define _LIBMAPLE_I2C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Series header must provide: + * + * - uint32 _i2c_bus_clk(i2c_dev*): Clock frequency of dev's bus, in + * MHz. (This is for internal use only). + * + * - (optional) _I2C_HAVE_IRQ_FIXUP: Leave undefined, or define to 1. + * This is for internal use only. It's a hack to work around a + * silicon bug related to I2C IRQ pre-emption on some targets. If 1, + * the series header must also declare and implement a routine with + * this signature (it may also be provided as a macro): + * + * void _i2c_irq_priority_fixup(i2c_dev*) + * + * This will be called by i2c_enable_irq() before actually enabling + * I2C interrupts. + * + * - Reg. map base pointers, device pointer declarations. + */ + + /* Roger clark. Replaced with line below #include */ +#include "libmaple/i2c_common_slave.h" +#include "stm32f1/include/series/i2c.h" + +#include +#include +#include +#include + +/** I2C register map type */ +typedef struct i2c_reg_map { + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 OAR1; /**< Own address register 1 */ + __IO uint32 OAR2; /**< Own address register 2 */ + __IO uint32 DR; /**< Data register */ + __IO uint32 SR1; /**< Status register 1 */ + __IO uint32 SR2; /**< Status register 2 */ + __IO uint32 CCR; /**< Clock control register */ + __IO uint32 TRISE; /**< TRISE (rise time) register */ +} i2c_reg_map; + +/** + * @brief I2C message type + */ +typedef struct i2c_msg { + uint16 addr; /**< Address */ + +#define I2C_MSG_READ 0x1 +#define I2C_MSG_10BIT_ADDR 0x2 + /** + * Bitwise OR of: + * - I2C_MSG_READ (write is default) + * - I2C_MSG_10BIT_ADDR (7-bit is default) */ + uint16 flags; + + uint16 length; /**< Message length */ + uint16 xferred; /**< Messages transferred */ + uint8 *data; /**< Data */ +} i2c_msg; + +/* + * Register bit definitions + */ + +/* Control register 1 */ + +#define I2C_CR1_SWRST (1U << 15) // Software reset +#define I2C_CR1_ALERT (1U << 13) // SMBus alert +#define I2C_CR1_PEC (1U << 12) // Packet error checking +#define I2C_CR1_POS (1U << 11) // Acknowledge/PEC position +#define I2C_CR1_ACK (1U << 10) // Acknowledge enable +#define I2C_CR1_STOP (1U << 9) // Stop generation +#define I2C_CR1_START (1U << 8) // Start generation +#define I2C_CR1_NOSTRETCH (1U << 7) // Clock stretching disable +#define I2C_CR1_ENGC (1U << 6) // General call enable +#define I2C_CR1_ENPEC (1U << 5) // PEC enable +#define I2C_CR1_ENARP (1U << 4) // ARP enable +#define I2C_CR1_SMBTYPE (1U << 3) // SMBus type +#define I2C_CR1_SMBTYPE_DEVICE (0U << 3) // SMBus type: device +#define I2C_CR1_SMBTYPE_HOST (1U << 3) // SMBus type: host +#define I2C_CR1_SMBUS (1U << 1) // SMBus mode +#define I2C_CR1_SMBUS_I2C (0U << 1) // SMBus mode: I2C +#define I2C_CR1_SMBUS_SMBUS (1U << 1) // SMBus mode: SMBus +#define I2C_CR1_PE (1U << 0) // Peripheral Enable + +/* Control register 2 */ + +#define I2C_CR2_LAST (1U << 12) // DMA last transfer +#define I2C_CR2_DMAEN (1U << 11) // DMA requests enable +#define I2C_CR2_ITBUFEN (1U << 10) // Buffer interrupt enable +#define I2C_CR2_ITEVTEN (1U << 9) // Event interupt enable +#define I2C_CR2_ITERREN (1U << 8) // Error interupt enable +#define I2C_CR2_FREQ 0x3F // Peripheral input frequency + +/* Own address register 1 */ + +#define I2C_OAR1_ADDMODE (1U << 15) // Addressing mode +#define I2C_OAR1_ADDMODE_7_BIT (0U << 15) // Addressing mode: 7-bit +#define I2C_OAR1_ADDMODE_10_BIT (1U << 15) // Addressing mode: 10-bit +#define I2C_OAR1_ADD 0x3FF // Interface address + +/* Own address register 2 */ + +#define I2C_OAR2_ADD2 0xFE // Interface address +#define I2C_OAR2_ENDUAL 1U // Dual addressing mode enable + +/* Status register 1 */ + +#define I2C_SR1_SMBALERT (1U << 15) // SMBus alert +#define I2C_SR1_TIMEOUT (1U << 14) // Timeout or Tlow error +#define I2C_SR1_PECERR (1U << 12) // PEC Error in reception +#define I2C_SR1_OVR (1U << 11) // Overrun/underrun +#define I2C_SR1_AF (1U << 10) // Acknowledge failure +#define I2C_SR1_ARLO (1U << 9) // Arbitration lost +#define I2C_SR1_BERR (1U << 8) // Bus error +#define I2C_SR1_TXE (1U << 7) // Data register empty +#define I2C_SR1_RXNE (1U << 6) // Data register not empty +#define I2C_SR1_STOPF (1U << 4) // Stop detection +#define I2C_SR1_ADD10 (1U << 3) // 10-bit header sent +#define I2C_SR1_BTF (1U << 2) // Byte transfer finished +#define I2C_SR1_ADDR (1U << 1) // Address sent/matched +#define I2C_SR1_SB (1U << 0) // Start bit + +/* Status register 2 */ + +#define I2C_SR2_PEC 0xFF00 // Packet error checking register +#define I2C_SR2_DUALF (1U << 7) // Dual flag +#define I2C_SR2_SMBHOST (1U << 6) // SMBus host header +#define I2C_SR2_SMBDEFAULT (1U << 5) // SMBus device default address +#define I2C_SR2_GENCALL (1U << 4) // General call address +#define I2C_SR2_TRA (1U << 2) // Transmitter/receiver +#define I2C_SR2_BUSY (1U << 1) // Bus busy +#define I2C_SR2_MSL (1U << 0) // Master/slave + +/* Clock control register */ + +#define I2C_CCR_FS (1U << 15) // Fast mode selection +#define I2C_CCR_DUTY (1U << 14) // Fast mode duty cycle +#define I2C_CCR_DUTY_2_1 (0U << 14) // Fast mode duty: 2/1 +#define I2C_CCR_DUTY_16_9 (1U << 14) // Fast mode duty: 16/9 +#define I2C_CCR_CCR 0xFFF // Clock control bits + +/* + * Convenience routines + */ + +/* Main I2C API */ + +/* I2C enable options */ +#define I2C_FAST_MODE 0x1 // 400 khz +#define I2C_DUTY_16_9 0x2 // 16/9 duty ratio +/* Flag 0x4 is reserved; DO NOT USE. */ +#define I2C_BUS_RESET 0x8 // Perform a bus reset +#define I2C_SLAVE_USE_RX_BUFFER 0x10 // Use a buffered message when doing a slave recv +#define I2C_SLAVE_USE_TX_BUFFER 0x20 // Use a buffered message when doing a slave transmit +#define I2C_SLAVE_DUAL_ADDRESS 0x40 // Enable the dual slave address scheme +#define I2C_SLAVE_GENERAL_CALL 0x80 // Enable the general call on address 0x00 +void i2c_master_enable(i2c_dev *dev, uint32 flags); +void i2c_slave_enable(i2c_dev *dev, uint32 flags); + +#define I2C_ERROR_PROTOCOL (-1) +#define I2C_ERROR_TIMEOUT (-2) +int32 i2c_master_xfer(i2c_dev *dev, i2c_msg *msgs, uint16 num, uint32 timeout); + +void i2c_bus_reset(const i2c_dev *dev); + +/** + * @brief Disable an I2C device + * + * This function disables the corresponding peripheral and marks dev's + * state as I2C_STATE_DISABLED. + * + * @param dev Device to disable. + */ +static inline void i2c_disable(i2c_dev *dev) { + dev->regs->CR1 &= ~I2C_CR1_PE; + dev->state = I2C_STATE_DISABLED; +} + +/* Start/stop conditions */ + +/** + * @brief Generate a start condition on the bus. + * @param dev I2C device + */ +static inline void i2c_start_condition(i2c_dev *dev) { + uint32 cr1; + while ((cr1 = dev->regs->CR1) & (I2C_CR1_START | + I2C_CR1_STOP | + I2C_CR1_PEC)) { + ; + } + dev->regs->CR1 |= I2C_CR1_START; +} + +/** + * @brief Generate a stop condition on the bus + * @param dev I2C device + */ +static inline void i2c_stop_condition(i2c_dev *dev) { + uint32 cr1; + while ((cr1 = dev->regs->CR1) & (I2C_CR1_START | + I2C_CR1_STOP | + I2C_CR1_PEC)) { + ; + } + dev->regs->CR1 |= I2C_CR1_STOP; + while ((cr1 = dev->regs->CR1) & (I2C_CR1_START | + I2C_CR1_STOP | + I2C_CR1_PEC)) { + ; + } + +} + +/* IRQ enable/disable */ + +#ifndef _I2C_HAVE_IRQ_FIXUP +/* The series header provides this if _I2C_HAVE_IRQ_FIXUP is defined, + * but we need it either way. */ +#define _i2c_irq_priority_fixup(dev) ((void)0) +#endif + +#define I2C_IRQ_ERROR I2C_CR2_ITERREN +#define I2C_IRQ_EVENT I2C_CR2_ITEVTEN +#define I2C_IRQ_BUFFER I2C_CR2_ITBUFEN +/** + * @brief Enable one or more I2C interrupts + * @param dev I2C device + * @param irqs Bitwise or of: + * I2C_IRQ_ERROR (error interrupt), + * I2C_IRQ_EVENT (event interrupt), and + * I2C_IRQ_BUFFER (buffer interrupt). + */ +static inline void i2c_enable_irq(i2c_dev *dev, uint32 irqs) { + _i2c_irq_priority_fixup(dev); + dev->regs->CR2 |= irqs; +} + +/** + * @brief Disable one or more I2C interrupts + * @param dev I2C device + * @param irqs Bitwise or of: + * I2C_IRQ_ERROR (error interrupt), + * I2C_IRQ_EVENT (event interrupt), and + * I2C_IRQ_BUFFER (buffer interrupt). + */ +static inline void i2c_disable_irq(i2c_dev *dev, uint32 irqs) { + dev->regs->CR2 &= ~irqs; +} + +/* ACK/NACK */ + +/** + * @brief Enable I2C acknowledgment + * @param dev I2C device + */ +static inline void i2c_enable_ack(i2c_dev *dev) { + dev->regs->CR1 |= I2C_CR1_ACK; +} + +/** + * @brief Disable I2C acknowledgment + * @param dev I2C device + */ +static inline void i2c_disable_ack(i2c_dev *dev) { + dev->regs->CR1 &= ~I2C_CR1_ACK; +} + +/* GPIO control */ + +/** + * @brief Configure device GPIOs. + * + * Configure GPIO bits dev->sda_pin and dev->scl_pin on GPIO device + * dev->gpio_port for use with I2C device dev. + * + * @param dev I2C Device + * @see i2c_release_gpios() + */ +extern void i2c_config_gpios(const i2c_dev *dev); + +/** + * @brief Release GPIOs controlling an I2C bus + * + * Releases the I2C bus controlled by dev as master, and disconnects + * GPIO bits dev->sda_pin and dev->scl_pin on GPIO device + * dev->gpio_port from I2C device dev. + * + * @param dev I2C device + * @see i2c_config_gpios() + */ +extern void i2c_master_release_bus(const i2c_dev *dev); + +/* Miscellaneous low-level routines */ + +void i2c_init(i2c_dev *dev); + +/** + * @brief Turn on an I2C peripheral + * @param dev Device to enable + */ +static inline void i2c_peripheral_enable(i2c_dev *dev) { + dev->regs->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Turn off an I2C peripheral + * @param dev Device to turn off + */ +static inline void i2c_peripheral_disable(i2c_dev *dev) { + dev->regs->CR1 &= ~I2C_CR1_PE; +} + +/** + * @brief Fill transmit register + * @param dev I2C device + * @param byte Byte to write + */ +static inline void i2c_write(i2c_dev *dev, uint8 byte) { + dev->regs->DR = byte; +} + +/** + * @brief Set input clock frequency, in MHz + * @param dev I2C device + * @param freq Frequency, in MHz. This must be at least 2, and at most + * the APB frequency of dev's bus. (For example, if + * rcc_dev_clk(dev) == RCC_APB1, freq must be at most + * PCLK1, in MHz). There is an additional limit of 46 MHz. + */ +static inline void i2c_set_input_clk(i2c_dev *dev, uint32 freq) { +#define I2C_MAX_FREQ_MHZ 46 + ASSERT(2 <= freq && freq <= _i2c_bus_clk(dev) && freq <= I2C_MAX_FREQ_MHZ); + uint32 cr2 = dev->regs->CR2; + cr2 &= ~I2C_CR2_FREQ; + cr2 |= freq; + dev->regs->CR2 = freq; +#undef I2C_MAX_FREQ_MHZ +} + +/** + * @brief Set I2C clock control register. + * + * See the chip reference manual for the details. + * + * @param dev I2C device + * @param val Value to use for clock control register (in + * Fast/Standard mode) + */ +static inline void i2c_set_clk_control(i2c_dev *dev, uint32 val) { + uint32 ccr = dev->regs->CCR; + ccr &= ~I2C_CCR_CCR; + ccr |= val; + dev->regs->CCR = ccr; +} + +/** + * @brief Set SCL rise time + * @param dev I2C device + * @param trise Maximum rise time in fast/standard mode (see chip + * reference manual for the relevant formulas). + */ +static inline void i2c_set_trise(i2c_dev *dev, uint32 trise) { + dev->regs->TRISE = trise; +} + +/* + * Slave support + */ + +/** + * @brief Enable Dual addressing mode to allow peripheral to have 2 addresses + * @param dev I2C device + */ +static inline void i2c_slave_dual_address_enable(i2c_dev *dev) { + dev->regs->OAR2 |= I2C_OAR2_ENDUAL; +} + +/** + * @brief Enable General Call to allow the unit to respond on addr 0x00 + * @param dev I2C device + */ +static inline void i2c_slave_general_call_enable(i2c_dev *dev) { + dev->regs->CR1 |= I2C_CR1_ENGC; +} + +/* callback functions */ +/* Callback handler for data received over the bus */ +void i2c_slave_attach_recv_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_recv_callback_func func); + +/* Callback handler for data being requested over the bus + * The callback function must call i2c_write to get the data over the bus + */ +void i2c_slave_attach_transmit_handler(i2c_dev *dev, i2c_msg *msg, i2c_slave_transmit_callback_func func); + +/** + * @brief Set the primary I2c slave address + * @param dev I2C device + * @param address the 8 or 10 bit i2c address + */ +static inline void i2c_slave_set_own_address(i2c_dev *dev, uint16 address) { + dev->regs->OAR1 = address <<1; +} + +/** + * @brief Set the secondary I2c slave address + * @param dev I2C device + * @param address the 8 or 10 bit i2c address + */ +static inline void i2c_slave_set_own_address2(i2c_dev *dev, uint16 address) { +dev->regs->OAR2 = (address <<1 ) | I2C_OAR2_ENDUAL; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/STM32F1/libraries/stm_fft/cr4_fft_1024_stm32.asm b/STM32F1/libraries/stm_fft/cr4_fft_1024_stm32.asm new file mode 100644 index 0000000..26c1726 --- /dev/null +++ b/STM32F1/libraries/stm_fft/cr4_fft_1024_stm32.asm @@ -0,0 +1,577 @@ +/*;******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +;* File Name : cr4_fft_1024_stm32.s +;* Author : MCD Application Team +;* Version : V2.0.0 +;* Date : 04/27/2009 +;* Description : Optimized 1024-point radix-4 complex FFT for Cortex-M3 +;******************************************************************************** +;* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +;* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +;* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +;* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +;* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +;* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;*******************************************************************************/ + +.cpu cortex-m3 +.fpu softvfp +.syntax unified +.thumb +.text + +.global cr4_fft_1024_stm32 +.extern TableFFT + +.equ NPT, 1024 + + +/*;******************************************************************************* +;* Function Name : cr4_fft_1024_stm32 +;* Description : complex radix-4 1024 points FFT +;* Input : - R0 = pssOUT: Output array . +;* - R1 = pssIN: Input array +;* - R2 = Nbin: =1024 number of points, this optimized FFT function +;* can only convert 1024 points. +;* Output : None +;* Return : None +;*********************************************************************************/ +.thumb_func +cr4_fft_1024_stm32: + + STMFD SP!, {R4-R11, LR} + + MOV r12, #0 + MOV r3, r0 + MOV r0,#0 + +preloop_v7: + ADD r14, r1, r12, LSR#22 /*1024pts*/ + + LDRSH r5, [r14, #2] + LDRSH r4, [r14] + ADD r14, #NPT + LDRSH r9, [r14, #2] + LDRSH r8, [r14] + ADD r14, #NPT + LDRSH r7, [r14, #2] + LDRSH r6, [r14] + ADD r14, #NPT + LDRSH r11, [r14, #2] + LDRSH r10, [r14] + ADD r14, #NPT + + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#2 + ADD r5, r5, r7, ASR#2 + SUB r6, r4, r6, ASR#1 + SUB r7, r5, r7, ASR#1 + + ADD r4, r4, r8, ASR#2 + ADD r5, r5, r9, ASR#2 + SUB r8, r4, r8, ASR#1 + SUB r9, r5, r9, ASR#1 + + ADD r6, r6, r11, ASR#2 + SUB r7, r7, r10, ASR#2 + SUB r11, r6, r11, ASR#1 + ADD r10, r7, r10, ASR#1 + + STRH r5, [r3, #2] + STRH r4, [r3], #4 + STRH r7, [r3, #2] + STRH r6, [r3], #4 + STRH r9, [r3, #2] + STRH r8, [r3], #4 + STRH r10, [r3, #2] + STRH r11, [r3], #4 + + ADD r0, r0, #1 + + RBIT r12, r0 + + CMP r0,#256 /*1024pts*/ + BNE preloop_v7 + + SUB r1, r3, r2, LSL#2 + MOV r0, #16 + MOVS r2, r2, LSR#4 + +/*;------------------------------------------------------------------------------ +; The FFT coefficients table can be stored into Flash or RAM. +; The following two lines of code allow selecting the method for coefficients +; storage. +; In the case of choosing coefficients in RAM, you have to: +; 1. Include the file table_fft.h, which is a part of the DSP library, +; in your main file. +; 2. Decomment the line LDR.W pssK, =TableFFT and comment the line +; ADRL pssK, TableFFT_V7 +; 3. Comment all the TableFFT_V7 data. +;------------------------------------------------------------------------------*/ + ADR r3, TableFFT_V7 + /*LDR.W r3, =TableFFT*/ + + +passloop_v7: + STMFD SP!, {r1,r2} + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + SUB r2, r2, #1<<16 + +grouploop_v7: + ADD r2,r2,r0,LSL#(16-2) + +butterloop_v7: + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r11, [r3, #2] + LDRSH r10, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r11 + ADD r14, r10, r11, LSL#1 + MLA r11, r5, r10, r12 + MLA r10, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r9, [r3, #2] + LDRSH r8, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r9 + ADD r14, r8, r9, LSL#1 + MLA r9, r5, r8, r12 + MLA r8, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r7, [r3, #2] + LDRSH r6, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r7 + ADD r14, r6, r7, LSL#1 + MLA r7, r5, r6, r12 + MLA r6, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#(2+14) + ADD r5, r5, r7, ASR#(2+14) + SUB r6, r4, r6, ASR#(1+14) + SUB r7, r5, r7, ASR#(1+14) + + ADD r4, r4, r8, ASR#(2+14) + ADD r5, r5, r9, ASR#(2+14) + SUB r8, r4, r8, ASR#(1+14) + SUB r9, r5, r9, ASR#(1+14) + + ADD r6, r6, r11, ASR#(2+14) + SUB r7, r7, r10, ASR#(2+14) + SUB r11, r6, r11, ASR#(1+14) + ADD r10, r7, r10, ASR#(1+14) + + STRH r5, [r1, #2] + STRH r4, [r1] + ADD r1, r1, r0 + STRH r7, [r1, #2] + STRH r6, [r1] + ADD r1, r1, r0 + STRH r9, [r1, #2] + STRH r8, [r1] + ADD r1, r1, r0 + STRH r10, [r1, #2] + STRH r11, [r1], #4 + SUBS r2,r2, #1<<16 + BGE butterloop_v7 + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + + SUB r2, r2, #1 + MOVS r14, r2, LSL#16 + IT ne + SUBNE r3, r3, r12 + BNE grouploop_v7 + + LDMFD sp!, {r1, r2} + MOV r0,r0,LSL#2 + MOVS r2, r2, LSR#2 + BNE passloop_v7 + LDMFD SP!, {R4-R11, PC} + + +TableFFT_V7: + + /*N=16*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + /*N=64*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + /*N=256*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x3b1e,0x04b5, 0x3e69,0x0192, 0x3cc8,0x0324 + .short 0x35eb,0x0964, 0x3cc8,0x0324, 0x396b,0x0646 + .short 0x306c,0x0e06, 0x3b1e,0x04b5, 0x35eb,0x0964 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x24ae,0x1709, 0x37af,0x07d6, 0x2e88,0x0f8d + .short 0x1e7e,0x1b5d, 0x35eb,0x0964, 0x2aaa,0x1294 + .short 0x1824,0x1f8c, 0x341e,0x0af1, 0x26b3,0x1590 + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0x0b14,0x2760, 0x306c,0x0e06, 0x1e7e,0x1b5d + .short 0x0471,0x2afb, 0x2e88,0x0f8d, 0x1a46,0x1e2b + .short 0xfdc7,0x2e5a, 0x2c9d,0x1112, 0x15fe,0x20e7 + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xf087,0x3453, 0x28b2,0x1413, 0x0d48,0x2620 + .short 0xea02,0x36e5, 0x26b3,0x1590, 0x08df,0x289a + .short 0xe39c,0x392b, 0x24ae,0x1709, 0x0471,0x2afb + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xd74e,0x3cc5, 0x2093,0x19ef, 0xfb8f,0x2f6c + .short 0xd178,0x3e15, 0x1e7e,0x1b5d, 0xf721,0x3179 + .short 0xcbe2,0x3f0f, 0x1c64,0x1cc6, 0xf2b8,0x3368 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xc197,0x3ffb, 0x1824,0x1f8c, 0xea02,0x36e5 + .short 0xbcf0,0x3fec, 0x15fe,0x20e7, 0xe5ba,0x3871 + .short 0xb8a6,0x3f85, 0x13d5,0x223d, 0xe182,0x39db + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xb140,0x3daf, 0x0f79,0x24da, 0xd94d,0x3c42 + .short 0xae2e,0x3c42, 0x0d48,0x2620, 0xd556,0x3d3f + .short 0xab8e,0x3a82, 0x0b14,0x2760, 0xd178,0x3e15 + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa7b1,0x3612, 0x06a9,0x29ce, 0xca15,0x3f4f + .short 0xa678,0x3368, 0x0471,0x2afb, 0xc695,0x3fb1 + .short 0xa5bc,0x3076, 0x0239,0x2c21, 0xc338,0x3fec + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa5bc,0x29ce, 0xfdc7,0x2e5a, 0xbcf0,0x3fec + .short 0xa678,0x2620, 0xfb8f,0x2f6c, 0xba09,0x3fb1 + .short 0xa7b1,0x223d, 0xf957,0x3076, 0xb74d,0x3f4f + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xab8e,0x19ef, 0xf4ec,0x3274, 0xb25e,0x3e15 + .short 0xae2e,0x1590, 0xf2b8,0x3368, 0xb02d,0x3d3f + .short 0xb140,0x1112, 0xf087,0x3453, 0xae2e,0x3c42 + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xb8a6,0x07d6, 0xec2b,0x3612, 0xaac8,0x39db + .short 0xbcf0,0x0324, 0xea02,0x36e5, 0xa963,0x3871 + .short 0xc197,0xfe6e, 0xe7dc,0x37b0, 0xa834,0x36e5 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xcbe2,0xf50f, 0xe39c,0x392b, 0xa678,0x3368 + .short 0xd178,0xf073, 0xe182,0x39db, 0xa5ed,0x3179 + .short 0xd74e,0xebed, 0xdf6d,0x3a82, 0xa599,0x2f6c + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xe39c,0xe33a, 0xdb52,0x3bb6, 0xa599,0x2afb + .short 0xea02,0xdf19, 0xd94d,0x3c42, 0xa5ed,0x289a + .short 0xf087,0xdb26, 0xd74e,0x3cc5, 0xa678,0x2620 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0xfdc7,0xd3df, 0xd363,0x3daf, 0xa834,0x20e7 + .short 0x0471,0xd094, 0xd178,0x3e15, 0xa963,0x1e2b + .short 0x0b14,0xcd8c, 0xcf94,0x3e72, 0xaac8,0x1b5d + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x1824,0xc850, 0xcbe2,0x3f0f, 0xae2e,0x1590 + .short 0x1e7e,0xc625, 0xca15,0x3f4f, 0xb02d,0x1294 + .short 0x24ae,0xc44a, 0xc851,0x3f85, 0xb25e,0x0f8d + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + .short 0x306c,0xc18e, 0xc4e2,0x3fd4, 0xb74d,0x0964 + .short 0x35eb,0xc0b1, 0xc338,0x3fec, 0xba09,0x0646 + .short 0x3b1e,0xc02c, 0xc197,0x3ffb, 0xbcf0,0x0324 + /*N=1024*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x3ed0,0x012e, 0x3f9b,0x0065, 0x3f36,0x00c9 + .short 0x3d9a,0x025b, 0x3f36,0x00c9, 0x3e69,0x0192 + .short 0x3c5f,0x0388, 0x3ed0,0x012e, 0x3d9a,0x025b + .short 0x3b1e,0x04b5, 0x3e69,0x0192, 0x3cc8,0x0324 + .short 0x39d9,0x05e2, 0x3e02,0x01f7, 0x3bf4,0x03ed + .short 0x388e,0x070e, 0x3d9a,0x025b, 0x3b1e,0x04b5 + .short 0x373f,0x0839, 0x3d31,0x02c0, 0x3a46,0x057e + .short 0x35eb,0x0964, 0x3cc8,0x0324, 0x396b,0x0646 + .short 0x3492,0x0a8e, 0x3c5f,0x0388, 0x388e,0x070e + .short 0x3334,0x0bb7, 0x3bf4,0x03ed, 0x37af,0x07d6 + .short 0x31d2,0x0cdf, 0x3b8a,0x0451, 0x36ce,0x089d + .short 0x306c,0x0e06, 0x3b1e,0x04b5, 0x35eb,0x0964 + .short 0x2f02,0x0f2b, 0x3ab2,0x051a, 0x3505,0x0a2b + .short 0x2d93,0x1050, 0x3a46,0x057e, 0x341e,0x0af1 + .short 0x2c21,0x1173, 0x39d9,0x05e2, 0x3334,0x0bb7 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x2931,0x13b4, 0x38fd,0x06aa, 0x315b,0x0d41 + .short 0x27b3,0x14d2, 0x388e,0x070e, 0x306c,0x0e06 + .short 0x2632,0x15ee, 0x381f,0x0772, 0x2f7b,0x0eca + .short 0x24ae,0x1709, 0x37af,0x07d6, 0x2e88,0x0f8d + .short 0x2326,0x1821, 0x373f,0x0839, 0x2d93,0x1050 + .short 0x219c,0x1937, 0x36ce,0x089d, 0x2c9d,0x1112 + .short 0x200e,0x1a4b, 0x365d,0x0901, 0x2ba4,0x11d3 + .short 0x1e7e,0x1b5d, 0x35eb,0x0964, 0x2aaa,0x1294 + .short 0x1ceb,0x1c6c, 0x3578,0x09c7, 0x29af,0x1354 + .short 0x1b56,0x1d79, 0x3505,0x0a2b, 0x28b2,0x1413 + .short 0x19be,0x1e84, 0x3492,0x0a8e, 0x27b3,0x14d2 + .short 0x1824,0x1f8c, 0x341e,0x0af1, 0x26b3,0x1590 + .short 0x1688,0x2091, 0x33a9,0x0b54, 0x25b1,0x164c + .short 0x14ea,0x2193, 0x3334,0x0bb7, 0x24ae,0x1709 + .short 0x134a,0x2292, 0x32bf,0x0c1a, 0x23a9,0x17c4 + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0x1005,0x2488, 0x31d2,0x0cdf, 0x219c,0x1937 + .short 0x0e61,0x257e, 0x315b,0x0d41, 0x2093,0x19ef + .short 0x0cbb,0x2671, 0x30e4,0x0da4, 0x1f89,0x1aa7 + .short 0x0b14,0x2760, 0x306c,0x0e06, 0x1e7e,0x1b5d + .short 0x096d,0x284c, 0x2ff4,0x0e68, 0x1d72,0x1c12 + .short 0x07c4,0x2935, 0x2f7b,0x0eca, 0x1c64,0x1cc6 + .short 0x061b,0x2a1a, 0x2f02,0x0f2b, 0x1b56,0x1d79 + .short 0x0471,0x2afb, 0x2e88,0x0f8d, 0x1a46,0x1e2b + .short 0x02c7,0x2bd8, 0x2e0e,0x0fee, 0x1935,0x1edc + .short 0x011c,0x2cb2, 0x2d93,0x1050, 0x1824,0x1f8c + .short 0xff72,0x2d88, 0x2d18,0x10b1, 0x1711,0x203a + .short 0xfdc7,0x2e5a, 0x2c9d,0x1112, 0x15fe,0x20e7 + .short 0xfc1d,0x2f28, 0x2c21,0x1173, 0x14ea,0x2193 + .short 0xfa73,0x2ff2, 0x2ba4,0x11d3, 0x13d5,0x223d + .short 0xf8ca,0x30b8, 0x2b28,0x1234, 0x12bf,0x22e7 + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xf579,0x3236, 0x2a2d,0x12f4, 0x1091,0x2435 + .short 0xf3d2,0x32ef, 0x29af,0x1354, 0x0f79,0x24da + .short 0xf22c,0x33a3, 0x2931,0x13b4, 0x0e61,0x257e + .short 0xf087,0x3453, 0x28b2,0x1413, 0x0d48,0x2620 + .short 0xeee3,0x34ff, 0x2833,0x1473, 0x0c2e,0x26c1 + .short 0xed41,0x35a5, 0x27b3,0x14d2, 0x0b14,0x2760 + .short 0xeba1,0x3648, 0x2733,0x1531, 0x09fa,0x27fe + .short 0xea02,0x36e5, 0x26b3,0x1590, 0x08df,0x289a + .short 0xe865,0x377e, 0x2632,0x15ee, 0x07c4,0x2935 + .short 0xe6cb,0x3812, 0x25b1,0x164c, 0x06a9,0x29ce + .short 0xe532,0x38a1, 0x252f,0x16ab, 0x058d,0x2a65 + .short 0xe39c,0x392b, 0x24ae,0x1709, 0x0471,0x2afb + .short 0xe208,0x39b0, 0x242b,0x1766, 0x0355,0x2b8f + .short 0xe077,0x3a30, 0x23a9,0x17c4, 0x0239,0x2c21 + .short 0xdee9,0x3aab, 0x2326,0x1821, 0x011c,0x2cb2 + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xdbd5,0x3b92, 0x221f,0x18db, 0xfee4,0x2dcf + .short 0xda4f,0x3bfd, 0x219c,0x1937, 0xfdc7,0x2e5a + .short 0xd8cd,0x3c64, 0x2117,0x1993, 0xfcab,0x2ee4 + .short 0xd74e,0x3cc5, 0x2093,0x19ef, 0xfb8f,0x2f6c + .short 0xd5d3,0x3d21, 0x200e,0x1a4b, 0xfa73,0x2ff2 + .short 0xd45c,0x3d78, 0x1f89,0x1aa7, 0xf957,0x3076 + .short 0xd2e8,0x3dc9, 0x1f04,0x1b02, 0xf83c,0x30f9 + .short 0xd178,0x3e15, 0x1e7e,0x1b5d, 0xf721,0x3179 + .short 0xd00c,0x3e5c, 0x1df8,0x1bb8, 0xf606,0x31f8 + .short 0xcea5,0x3e9d, 0x1d72,0x1c12, 0xf4ec,0x3274 + .short 0xcd41,0x3ed8, 0x1ceb,0x1c6c, 0xf3d2,0x32ef + .short 0xcbe2,0x3f0f, 0x1c64,0x1cc6, 0xf2b8,0x3368 + .short 0xca88,0x3f40, 0x1bdd,0x1d20, 0xf19f,0x33df + .short 0xc932,0x3f6b, 0x1b56,0x1d79, 0xf087,0x3453 + .short 0xc7e1,0x3f91, 0x1ace,0x1dd3, 0xef6f,0x34c6 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xc54e,0x3fcc, 0x19be,0x1e84, 0xed41,0x35a5 + .short 0xc40c,0x3fe1, 0x1935,0x1edc, 0xec2b,0x3612 + .short 0xc2cf,0x3ff1, 0x18ad,0x1f34, 0xeb16,0x367d + .short 0xc197,0x3ffb, 0x1824,0x1f8c, 0xea02,0x36e5 + .short 0xc065,0x4000, 0x179b,0x1fe3, 0xe8ef,0x374b + .short 0xbf38,0x3fff, 0x1711,0x203a, 0xe7dc,0x37b0 + .short 0xbe11,0x3ff8, 0x1688,0x2091, 0xe6cb,0x3812 + .short 0xbcf0,0x3fec, 0x15fe,0x20e7, 0xe5ba,0x3871 + .short 0xbbd4,0x3fdb, 0x1574,0x213d, 0xe4aa,0x38cf + .short 0xbabf,0x3fc4, 0x14ea,0x2193, 0xe39c,0x392b + .short 0xb9af,0x3fa7, 0x145f,0x21e8, 0xe28e,0x3984 + .short 0xb8a6,0x3f85, 0x13d5,0x223d, 0xe182,0x39db + .short 0xb7a2,0x3f5d, 0x134a,0x2292, 0xe077,0x3a30 + .short 0xb6a5,0x3f30, 0x12bf,0x22e7, 0xdf6d,0x3a82 + .short 0xb5af,0x3efd, 0x1234,0x233b, 0xde64,0x3ad3 + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xb3d5,0x3e88, 0x111d,0x23e2, 0xdc57,0x3b6d + .short 0xb2f2,0x3e45, 0x1091,0x2435, 0xdb52,0x3bb6 + .short 0xb215,0x3dfc, 0x1005,0x2488, 0xda4f,0x3bfd + .short 0xb140,0x3daf, 0x0f79,0x24da, 0xd94d,0x3c42 + .short 0xb071,0x3d5b, 0x0eed,0x252c, 0xd84d,0x3c85 + .short 0xafa9,0x3d03, 0x0e61,0x257e, 0xd74e,0x3cc5 + .short 0xaee8,0x3ca5, 0x0dd4,0x25cf, 0xd651,0x3d03 + .short 0xae2e,0x3c42, 0x0d48,0x2620, 0xd556,0x3d3f + .short 0xad7b,0x3bda, 0x0cbb,0x2671, 0xd45c,0x3d78 + .short 0xacd0,0x3b6d, 0x0c2e,0x26c1, 0xd363,0x3daf + .short 0xac2b,0x3afa, 0x0ba1,0x2711, 0xd26d,0x3de3 + .short 0xab8e,0x3a82, 0x0b14,0x2760, 0xd178,0x3e15 + .short 0xaaf8,0x3a06, 0x0a87,0x27af, 0xd085,0x3e45 + .short 0xaa6a,0x3984, 0x09fa,0x27fe, 0xcf94,0x3e72 + .short 0xa9e3,0x38fd, 0x096d,0x284c, 0xcea5,0x3e9d + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa8eb,0x37e1, 0x0852,0x28e7, 0xcccc,0x3eeb + .short 0xa87b,0x374b, 0x07c4,0x2935, 0xcbe2,0x3f0f + .short 0xa812,0x36b1, 0x0736,0x2981, 0xcafb,0x3f30 + .short 0xa7b1,0x3612, 0x06a9,0x29ce, 0xca15,0x3f4f + .short 0xa757,0x356e, 0x061b,0x2a1a, 0xc932,0x3f6b + .short 0xa705,0x34c6, 0x058d,0x2a65, 0xc851,0x3f85 + .short 0xa6bb,0x3419, 0x04ff,0x2ab0, 0xc772,0x3f9c + .short 0xa678,0x3368, 0x0471,0x2afb, 0xc695,0x3fb1 + .short 0xa63e,0x32b2, 0x03e3,0x2b45, 0xc5ba,0x3fc4 + .short 0xa60b,0x31f8, 0x0355,0x2b8f, 0xc4e2,0x3fd4 + .short 0xa5e0,0x3139, 0x02c7,0x2bd8, 0xc40c,0x3fe1 + .short 0xa5bc,0x3076, 0x0239,0x2c21, 0xc338,0x3fec + .short 0xa5a1,0x2faf, 0x01aa,0x2c6a, 0xc266,0x3ff5 + .short 0xa58d,0x2ee4, 0x011c,0x2cb2, 0xc197,0x3ffb + .short 0xa581,0x2e15, 0x008e,0x2cfa, 0xc0ca,0x3fff + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa581,0x2c6a, 0xff72,0x2d88, 0xbf38,0x3fff + .short 0xa58d,0x2b8f, 0xfee4,0x2dcf, 0xbe73,0x3ffb + .short 0xa5a1,0x2ab0, 0xfe56,0x2e15, 0xbdb0,0x3ff5 + .short 0xa5bc,0x29ce, 0xfdc7,0x2e5a, 0xbcf0,0x3fec + .short 0xa5e0,0x28e7, 0xfd39,0x2e9f, 0xbc32,0x3fe1 + .short 0xa60b,0x27fe, 0xfcab,0x2ee4, 0xbb77,0x3fd4 + .short 0xa63e,0x2711, 0xfc1d,0x2f28, 0xbabf,0x3fc4 + .short 0xa678,0x2620, 0xfb8f,0x2f6c, 0xba09,0x3fb1 + .short 0xa6bb,0x252c, 0xfb01,0x2faf, 0xb956,0x3f9c + .short 0xa705,0x2435, 0xfa73,0x2ff2, 0xb8a6,0x3f85 + .short 0xa757,0x233b, 0xf9e5,0x3034, 0xb7f8,0x3f6b + .short 0xa7b1,0x223d, 0xf957,0x3076, 0xb74d,0x3f4f + .short 0xa812,0x213d, 0xf8ca,0x30b8, 0xb6a5,0x3f30 + .short 0xa87b,0x203a, 0xf83c,0x30f9, 0xb600,0x3f0f + .short 0xa8eb,0x1f34, 0xf7ae,0x3139, 0xb55e,0x3eeb + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xa9e3,0x1d20, 0xf693,0x31b9, 0xb422,0x3e9d + .short 0xaa6a,0x1c12, 0xf606,0x31f8, 0xb388,0x3e72 + .short 0xaaf8,0x1b02, 0xf579,0x3236, 0xb2f2,0x3e45 + .short 0xab8e,0x19ef, 0xf4ec,0x3274, 0xb25e,0x3e15 + .short 0xac2b,0x18db, 0xf45f,0x32b2, 0xb1cd,0x3de3 + .short 0xacd0,0x17c4, 0xf3d2,0x32ef, 0xb140,0x3daf + .short 0xad7b,0x16ab, 0xf345,0x332c, 0xb0b5,0x3d78 + .short 0xae2e,0x1590, 0xf2b8,0x3368, 0xb02d,0x3d3f + .short 0xaee8,0x1473, 0xf22c,0x33a3, 0xafa9,0x3d03 + .short 0xafa9,0x1354, 0xf19f,0x33df, 0xaf28,0x3cc5 + .short 0xb071,0x1234, 0xf113,0x3419, 0xaea9,0x3c85 + .short 0xb140,0x1112, 0xf087,0x3453, 0xae2e,0x3c42 + .short 0xb215,0x0fee, 0xeffb,0x348d, 0xadb6,0x3bfd + .short 0xb2f2,0x0eca, 0xef6f,0x34c6, 0xad41,0x3bb6 + .short 0xb3d5,0x0da4, 0xeee3,0x34ff, 0xacd0,0x3b6d + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xb5af,0x0b54, 0xedcc,0x356e, 0xabf6,0x3ad3 + .short 0xb6a5,0x0a2b, 0xed41,0x35a5, 0xab8e,0x3a82 + .short 0xb7a2,0x0901, 0xecb6,0x35dc, 0xab29,0x3a30 + .short 0xb8a6,0x07d6, 0xec2b,0x3612, 0xaac8,0x39db + .short 0xb9af,0x06aa, 0xeba1,0x3648, 0xaa6a,0x3984 + .short 0xbabf,0x057e, 0xeb16,0x367d, 0xaa0f,0x392b + .short 0xbbd4,0x0451, 0xea8c,0x36b1, 0xa9b7,0x38cf + .short 0xbcf0,0x0324, 0xea02,0x36e5, 0xa963,0x3871 + .short 0xbe11,0x01f7, 0xe978,0x3718, 0xa912,0x3812 + .short 0xbf38,0x00c9, 0xe8ef,0x374b, 0xa8c5,0x37b0 + .short 0xc065,0xff9b, 0xe865,0x377e, 0xa87b,0x374b + .short 0xc197,0xfe6e, 0xe7dc,0x37b0, 0xa834,0x36e5 + .short 0xc2cf,0xfd40, 0xe753,0x37e1, 0xa7f1,0x367d + .short 0xc40c,0xfc13, 0xe6cb,0x3812, 0xa7b1,0x3612 + .short 0xc54e,0xfae6, 0xe642,0x3842, 0xa774,0x35a5 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xc7e1,0xf88e, 0xe532,0x38a1, 0xa705,0x34c6 + .short 0xc932,0xf763, 0xe4aa,0x38cf, 0xa6d3,0x3453 + .short 0xca88,0xf639, 0xe423,0x38fd, 0xa6a4,0x33df + .short 0xcbe2,0xf50f, 0xe39c,0x392b, 0xa678,0x3368 + .short 0xcd41,0xf3e6, 0xe315,0x3958, 0xa650,0x32ef + .short 0xcea5,0xf2bf, 0xe28e,0x3984, 0xa62c,0x3274 + .short 0xd00c,0xf198, 0xe208,0x39b0, 0xa60b,0x31f8 + .short 0xd178,0xf073, 0xe182,0x39db, 0xa5ed,0x3179 + .short 0xd2e8,0xef4f, 0xe0fc,0x3a06, 0xa5d3,0x30f9 + .short 0xd45c,0xee2d, 0xe077,0x3a30, 0xa5bc,0x3076 + .short 0xd5d3,0xed0c, 0xdff2,0x3a59, 0xa5a9,0x2ff2 + .short 0xd74e,0xebed, 0xdf6d,0x3a82, 0xa599,0x2f6c + .short 0xd8cd,0xeacf, 0xdee9,0x3aab, 0xa58d,0x2ee4 + .short 0xda4f,0xe9b4, 0xde64,0x3ad3, 0xa585,0x2e5a + .short 0xdbd5,0xe89a, 0xdde1,0x3afa, 0xa57f,0x2dcf + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xdee9,0xe66d, 0xdcda,0x3b47, 0xa57f,0x2cb2 + .short 0xe077,0xe559, 0xdc57,0x3b6d, 0xa585,0x2c21 + .short 0xe208,0xe448, 0xdbd5,0x3b92, 0xa58d,0x2b8f + .short 0xe39c,0xe33a, 0xdb52,0x3bb6, 0xa599,0x2afb + .short 0xe532,0xe22d, 0xdad1,0x3bda, 0xa5a9,0x2a65 + .short 0xe6cb,0xe124, 0xda4f,0x3bfd, 0xa5bc,0x29ce + .short 0xe865,0xe01d, 0xd9ce,0x3c20, 0xa5d3,0x2935 + .short 0xea02,0xdf19, 0xd94d,0x3c42, 0xa5ed,0x289a + .short 0xeba1,0xde18, 0xd8cd,0x3c64, 0xa60b,0x27fe + .short 0xed41,0xdd19, 0xd84d,0x3c85, 0xa62c,0x2760 + .short 0xeee3,0xdc1e, 0xd7cd,0x3ca5, 0xa650,0x26c1 + .short 0xf087,0xdb26, 0xd74e,0x3cc5, 0xa678,0x2620 + .short 0xf22c,0xda31, 0xd6cf,0x3ce4, 0xa6a4,0x257e + .short 0xf3d2,0xd93f, 0xd651,0x3d03, 0xa6d3,0x24da + .short 0xf579,0xd851, 0xd5d3,0x3d21, 0xa705,0x2435 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0xf8ca,0xd67f, 0xd4d8,0x3d5b, 0xa774,0x22e7 + .short 0xfa73,0xd59b, 0xd45c,0x3d78, 0xa7b1,0x223d + .short 0xfc1d,0xd4bb, 0xd3df,0x3d93, 0xa7f1,0x2193 + .short 0xfdc7,0xd3df, 0xd363,0x3daf, 0xa834,0x20e7 + .short 0xff72,0xd306, 0xd2e8,0x3dc9, 0xa87b,0x203a + .short 0x011c,0xd231, 0xd26d,0x3de3, 0xa8c5,0x1f8c + .short 0x02c7,0xd161, 0xd1f2,0x3dfc, 0xa912,0x1edc + .short 0x0471,0xd094, 0xd178,0x3e15, 0xa963,0x1e2b + .short 0x061b,0xcfcc, 0xd0fe,0x3e2d, 0xa9b7,0x1d79 + .short 0x07c4,0xcf07, 0xd085,0x3e45, 0xaa0f,0x1cc6 + .short 0x096d,0xce47, 0xd00c,0x3e5c, 0xaa6a,0x1c12 + .short 0x0b14,0xcd8c, 0xcf94,0x3e72, 0xaac8,0x1b5d + .short 0x0cbb,0xccd4, 0xcf1c,0x3e88, 0xab29,0x1aa7 + .short 0x0e61,0xcc21, 0xcea5,0x3e9d, 0xab8e,0x19ef + .short 0x1005,0xcb73, 0xce2e,0x3eb1, 0xabf6,0x1937 + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x134a,0xca24, 0xcd41,0x3ed8, 0xacd0,0x17c4 + .short 0x14ea,0xc983, 0xcccc,0x3eeb, 0xad41,0x1709 + .short 0x1688,0xc8e8, 0xcc57,0x3efd, 0xadb6,0x164c + .short 0x1824,0xc850, 0xcbe2,0x3f0f, 0xae2e,0x1590 + .short 0x19be,0xc7be, 0xcb6e,0x3f20, 0xaea9,0x14d2 + .short 0x1b56,0xc731, 0xcafb,0x3f30, 0xaf28,0x1413 + .short 0x1ceb,0xc6a8, 0xca88,0x3f40, 0xafa9,0x1354 + .short 0x1e7e,0xc625, 0xca15,0x3f4f, 0xb02d,0x1294 + .short 0x200e,0xc5a7, 0xc9a3,0x3f5d, 0xb0b5,0x11d3 + .short 0x219c,0xc52d, 0xc932,0x3f6b, 0xb140,0x1112 + .short 0x2326,0xc4b9, 0xc8c1,0x3f78, 0xb1cd,0x1050 + .short 0x24ae,0xc44a, 0xc851,0x3f85, 0xb25e,0x0f8d + .short 0x2632,0xc3e0, 0xc7e1,0x3f91, 0xb2f2,0x0eca + .short 0x27b3,0xc37b, 0xc772,0x3f9c, 0xb388,0x0e06 + .short 0x2931,0xc31c, 0xc703,0x3fa7, 0xb422,0x0d41 + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + .short 0x2c21,0xc26d, 0xc627,0x3fbb, 0xb55e,0x0bb7 + .short 0x2d93,0xc21d, 0xc5ba,0x3fc4, 0xb600,0x0af1 + .short 0x2f02,0xc1d3, 0xc54e,0x3fcc, 0xb6a5,0x0a2b + .short 0x306c,0xc18e, 0xc4e2,0x3fd4, 0xb74d,0x0964 + .short 0x31d2,0xc14f, 0xc476,0x3fdb, 0xb7f8,0x089d + .short 0x3334,0xc115, 0xc40c,0x3fe1, 0xb8a6,0x07d6 + .short 0x3492,0xc0e0, 0xc3a1,0x3fe7, 0xb956,0x070e + .short 0x35eb,0xc0b1, 0xc338,0x3fec, 0xba09,0x0646 + .short 0x373f,0xc088, 0xc2cf,0x3ff1, 0xbabf,0x057e + .short 0x388e,0xc064, 0xc266,0x3ff5, 0xbb77,0x04b5 + .short 0x39d9,0xc045, 0xc1fe,0x3ff8, 0xbc32,0x03ed + .short 0x3b1e,0xc02c, 0xc197,0x3ffb, 0xbcf0,0x0324 + .short 0x3c5f,0xc019, 0xc130,0x3ffd, 0xbdb0,0x025b + .short 0x3d9a,0xc00b, 0xc0ca,0x3fff, 0xbe73,0x0192 + .short 0x3ed0,0xc003, 0xc065,0x4000, 0xbf38,0x00c9 + + +.end +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F1/libraries/stm_fft/cr4_fft_16_stm33.asm b/STM32F1/libraries/stm_fft/cr4_fft_16_stm33.asm new file mode 100644 index 0000000..1d60179 --- /dev/null +++ b/STM32F1/libraries/stm_fft/cr4_fft_16_stm33.asm @@ -0,0 +1,250 @@ +/*;******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +;* File Name : cr4_fft_64_stm32.s +;* Author : MCD Application Team +;* Version : V2.0.0 +;* Date : 04/27/2009 +;* Description : Optimized 64-point radix-4 complex FFT for Cortex-M3 +;******************************************************************************** +;* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +;* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +;* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +;* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +;* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +;* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;*******************************************************************************/ + +.cpu cortex-m3 +.fpu softvfp +.syntax unified +.thumb +.text + +.global cr4_fft_16_stm32 +.extern TableFFT + +.equ NPT, 16 + + +/*;******************************************************************************* +;* Function Name : cr4_fft_16_stm32 +;* Description : complex radix-4 16 points FFT +;* Input : - R0 = pssOUT: Output array . +;* - R1 = pssIN: Input array +;* - R2 = Nbin: = 16 number of points, this optimized FFT function +;* can only convert 16 points. +;* Output : None +;* Return : None +;********************************************************************************/ +.thumb_func +cr4_fft_16_stm32: + + STMFD SP!, {R4-R11, LR} + + MOV r12, #0 + MOV r3, r0 + MOV r0,#0 + +preloop_v7: + ADD r14, r1, r12, LSR#28 + + LDRSH r5, [r14, #2] + LDRSH r4, [r14],#NPT + LDRSH r9, [r14, #2] + LDRSH r8, [r14],#NPT + LDRSH r7, [r14, #2] + LDRSH r6, [r14],#NPT + LDRSH r11, [r14, #2] + LDRSH r10, [r14],#NPT + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#2 + ADD r5, r5, r7, ASR#2 + SUB r6, r4, r6, ASR#1 + SUB r7, r5, r7, ASR#1 + + ADD r4, r4, r8, ASR#2 + ADD r5, r5, r9, ASR#2 + SUB r8, r4, r8, ASR#1 + SUB r9, r5, r9, ASR#1 + + ADD r6, r6, r11, ASR#2 + SUB r7, r7, r10, ASR#2 + SUB r11, r6, r11, ASR#1 + ADD r10, r7, r10, ASR#1 + + STRH r5, [r3, #2] + STRH r4, [r3], #4 + STRH r7, [r3, #2] + STRH r6, [r3], #4 + STRH r9, [r3, #2] + STRH r8, [r3], #4 + STRH r10, [r3, #2] + STRH r11, [r3], #4 + + ADD r0, r0, #1 + + RBIT r12, r0 + + CMP r0,#4 + BNE preloop_v7 + + SUB r1, r3, r2, LSL#2 + MOV r0, #16 + MOVS r2, r2, LSR#4 + +/*;------------------------------------------------------------------------------ +; The FFT coefficients table can be stored into Flash or RAM. +; The following two lines of code allow selecting the method for coefficients +; storage. +; In the case of choosing coefficients in RAM, you have to: +; 1. Include the file table_fft.h, which is a part of the DSP library, +; in your main file. +; 2. Decomment the line LDR.W pssK, =TableFFT and comment the line +; ADRL pssK, TableFFT_V7 +; 3. Comment all the TableFFT_V7 data. +;------------------------------------------------------------------------------*/ + ADR r3, TableFFT_V7 + /*LDR.W r3, =TableFFT*/ + + +passloop_v7: + STMFD SP!, {r1,r2} + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + SUB r2, r2, #1<<16 + +grouploop_v7: + ADD r2,r2,r0,LSL#(16-2) + +butterloop_v7: + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r11, [r3, #2] + LDRSH r10, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r11 + ADD r14, r10, r11, LSL#1 + MLA r11, r5, r10, r12 + MLA r10, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r9, [r3, #2] + LDRSH r8, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r9 + ADD r14, r8, r9, LSL#1 + MLA r9, r5, r8, r12 + MLA r8, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r7, [r3, #2] + LDRSH r6, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r7 + ADD r14, r6, r7, LSL#1 + MLA r7, r5, r6, r12 + MLA r6, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#(2+14) + ADD r5, r5, r7, ASR#(2+14) + SUB r6, r4, r6, ASR#(1+14) + SUB r7, r5, r7, ASR#(1+14) + + ADD r4, r4, r8, ASR#(2+14) + ADD r5, r5, r9, ASR#(2+14) + SUB r8, r4, r8, ASR#(1+14) + SUB r9, r5, r9, ASR#(1+14) + + ADD r6, r6, r11, ASR#(2+14) + SUB r7, r7, r10, ASR#(2+14) + SUB r11, r6, r11, ASR#(1+14) + ADD r10, r7, r10, ASR#(1+14) + + STRH r5, [r1, #2] + STRH r4, [r1] + ADD r1, r1, r0 + STRH r7, [r1, #2] + STRH r6, [r1] + ADD r1, r1, r0 + STRH r9, [r1, #2] + STRH r8, [r1] + ADD r1, r1, r0 + STRH r10, [r1, #2] + STRH r11, [r1], #4 + SUBS r2,r2, #1<<16 + BGE butterloop_v7 + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + + SUB r2, r2, #1 + MOVS r14, r2, LSL#16 + IT ne + SUBNE r3, r3, r12 + BNE grouploop_v7 + + LDMFD sp!, {r1, r2} + MOV r0,r0,LSL#2 + MOVS r2, r2, LSR#2 + BNE passloop_v7 + LDMFD SP!, {R4-R11, PC} + + +TableFFT_V7: + /*N=16*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + /*N=64*/ + /* + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + */ + +.end +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F1/libraries/stm_fft/cr4_fft_256_stm32.asm b/STM32F1/libraries/stm_fft/cr4_fft_256_stm32.asm new file mode 100644 index 0000000..15e4b0c --- /dev/null +++ b/STM32F1/libraries/stm_fft/cr4_fft_256_stm32.asm @@ -0,0 +1,318 @@ +/*;******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +;* File Name : cr4_fft_256_stm32.s +;* Author : MCD Application Team +;* Version : V2.0.0 +;* Date : 04/27/2009 +;* Description : Optimized 256-point radix-4 complex FFT for Cortex-M3 +;******************************************************************************** +;* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +;* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +;* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +;* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +;* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +;* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;*******************************************************************************/ + +.cpu cortex-m3 +.fpu softvfp +.syntax unified +.thumb +.text + +.global cr4_fft_256_stm32 +.extern TableFFT + +.equ NPT, 256 + + +/*;******************************************************************************* +;* Function Name : cr4_fft_256_stm32 +;* Description : complex radix-4 256 points FFT +;* Input : - R0 = pssOUT: Output array . +;* - R1 = pssIN: Input array +;* - R2 = Nbin: =256 number of points, this optimized FFT function +;* can only convert 256 points. +;* Output : None +;* Return : None +;********************************************************************************/ +.thumb_func +cr4_fft_256_stm32: + + STMFD SP!, {R4-R11, LR} + + MOV r12, #0 + MOV r3, r0 + MOV r0,#0 + +preloop_v7: + ADD r14, r1, r12, LSR#24 /*256pts*/ + + LDRSH r5, [r14, #2] + LDRSH r4, [r14] + ADD r14, #NPT + LDRSH r9, [r14, #2] + LDRSH r8, [r14] + ADD r14, #NPT + LDRSH r7, [r14, #2] + LDRSH r6, [r14] + ADD r14, #NPT + LDRSH r11, [r14, #2] + LDRSH r10, [r14] + ADD r14, #NPT + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#2 + ADD r5, r5, r7, ASR#2 + SUB r6, r4, r6, ASR#1 + SUB r7, r5, r7, ASR#1 + + ADD r4, r4, r8, ASR#2 + ADD r5, r5, r9, ASR#2 + SUB r8, r4, r8, ASR#1 + SUB r9, r5, r9, ASR#1 + + ADD r6, r6, r11, ASR#2 + SUB r7, r7, r10, ASR#2 + SUB r11, r6, r11, ASR#1 + ADD r10, r7, r10, ASR#1 + + STRH r5, [r3, #2] + STRH r4, [r3], #4 + STRH r7, [r3, #2] + STRH r6, [r3], #4 + STRH r9, [r3, #2] + STRH r8, [r3], #4 + STRH r10, [r3, #2] + STRH r11, [r3], #4 + + ADD r0, r0, #1 + + RBIT r12, r0 + + CMP r0,#64 /*256pts*/ + BNE preloop_v7 + + SUB r1, r3, r2, LSL#2 + MOV r0, #16 + MOVS r2, r2, LSR#4 + +/*;------------------------------------------------------------------------------ +; The FFT coefficients table can be stored into Flash or RAM. +; The following two lines of code allow selecting the method for coefficients +; storage. +; In the case of choosing coefficients in RAM, you have to: +; 1. Include the file table_fft.h, which is a part of the DSP library, +; in your main file. +; 2. Decomment the line LDR.W pssK, =TableFFT and comment the line +; ADRL pssK, TableFFT_V7 +; 3. Comment all the TableFFT_V7 data. +;------------------------------------------------------------------------------*/ + ADR r3, TableFFT_V7 + /*LDR.W r3, =TableFFT*/ + + +passloop_v7: + STMFD SP!, {r1,r2} + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + SUB r2, r2, #1<<16 + +grouploop_v7: + ADD r2,r2,r0,LSL#(16-2) + +butterloop_v7: + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r11, [r3, #2] + LDRSH r10, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r11 + ADD r14, r10, r11, LSL#1 + MLA r11, r5, r10, r12 + MLA r10, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r9, [r3, #2] + LDRSH r8, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r9 + ADD r14, r8, r9, LSL#1 + MLA r9, r5, r8, r12 + MLA r8, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r7, [r3, #2] + LDRSH r6, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r7 + ADD r14, r6, r7, LSL#1 + MLA r7, r5, r6, r12 + MLA r6, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#(2+14) + ADD r5, r5, r7, ASR#(2+14) + SUB r6, r4, r6, ASR#(1+14) + SUB r7, r5, r7, ASR#(1+14) + + ADD r4, r4, r8, ASR#(2+14) + ADD r5, r5, r9, ASR#(2+14) + SUB r8, r4, r8, ASR#(1+14) + SUB r9, r5, r9, ASR#(1+14) + + ADD r6, r6, r11, ASR#(2+14) + SUB r7, r7, r10, ASR#(2+14) + SUB r11, r6, r11, ASR#(1+14) + ADD r10, r7, r10, ASR#(1+14) + + STRH r5, [r1, #2] + STRH r4, [r1] + ADD r1, r1, r0 + STRH r7, [r1, #2] + STRH r6, [r1] + ADD r1, r1, r0 + STRH r9, [r1, #2] + STRH r8, [r1] + ADD r1, r1, r0 + STRH r10, [r1, #2] + STRH r11, [r1], #4 + SUBS r2,r2, #1<<16 + BGE butterloop_v7 + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + + SUB r2, r2, #1 + MOVS r14, r2, LSL#16 + IT ne + SUBNE r3, r3, r12 + BNE grouploop_v7 + + LDMFD sp!, {r1, r2} + MOV r0,r0,LSL#2 + MOVS r2, r2, LSR#2 + BNE passloop_v7 + LDMFD SP!, {R4-R11, PC} + + +TableFFT_V7: + /*N=16*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + /*N=64*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + /*N=256*/ + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x3b1e,0x04b5, 0x3e69,0x0192, 0x3cc8,0x0324 + .short 0x35eb,0x0964, 0x3cc8,0x0324, 0x396b,0x0646 + .short 0x306c,0x0e06, 0x3b1e,0x04b5, 0x35eb,0x0964 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x24ae,0x1709, 0x37af,0x07d6, 0x2e88,0x0f8d + .short 0x1e7e,0x1b5d, 0x35eb,0x0964, 0x2aaa,0x1294 + .short 0x1824,0x1f8c, 0x341e,0x0af1, 0x26b3,0x1590 + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0x0b14,0x2760, 0x306c,0x0e06, 0x1e7e,0x1b5d + .short 0x0471,0x2afb, 0x2e88,0x0f8d, 0x1a46,0x1e2b + .short 0xfdc7,0x2e5a, 0x2c9d,0x1112, 0x15fe,0x20e7 + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xf087,0x3453, 0x28b2,0x1413, 0x0d48,0x2620 + .short 0xea02,0x36e5, 0x26b3,0x1590, 0x08df,0x289a + .short 0xe39c,0x392b, 0x24ae,0x1709, 0x0471,0x2afb + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xd74e,0x3cc5, 0x2093,0x19ef, 0xfb8f,0x2f6c + .short 0xd178,0x3e15, 0x1e7e,0x1b5d, 0xf721,0x3179 + .short 0xcbe2,0x3f0f, 0x1c64,0x1cc6, 0xf2b8,0x3368 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xc197,0x3ffb, 0x1824,0x1f8c, 0xea02,0x36e5 + .short 0xbcf0,0x3fec, 0x15fe,0x20e7, 0xe5ba,0x3871 + .short 0xb8a6,0x3f85, 0x13d5,0x223d, 0xe182,0x39db + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xb140,0x3daf, 0x0f79,0x24da, 0xd94d,0x3c42 + .short 0xae2e,0x3c42, 0x0d48,0x2620, 0xd556,0x3d3f + .short 0xab8e,0x3a82, 0x0b14,0x2760, 0xd178,0x3e15 + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa7b1,0x3612, 0x06a9,0x29ce, 0xca15,0x3f4f + .short 0xa678,0x3368, 0x0471,0x2afb, 0xc695,0x3fb1 + .short 0xa5bc,0x3076, 0x0239,0x2c21, 0xc338,0x3fec + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa5bc,0x29ce, 0xfdc7,0x2e5a, 0xbcf0,0x3fec + .short 0xa678,0x2620, 0xfb8f,0x2f6c, 0xba09,0x3fb1 + .short 0xa7b1,0x223d, 0xf957,0x3076, 0xb74d,0x3f4f + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xab8e,0x19ef, 0xf4ec,0x3274, 0xb25e,0x3e15 + .short 0xae2e,0x1590, 0xf2b8,0x3368, 0xb02d,0x3d3f + .short 0xb140,0x1112, 0xf087,0x3453, 0xae2e,0x3c42 + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xb8a6,0x07d6, 0xec2b,0x3612, 0xaac8,0x39db + .short 0xbcf0,0x0324, 0xea02,0x36e5, 0xa963,0x3871 + .short 0xc197,0xfe6e, 0xe7dc,0x37b0, 0xa834,0x36e5 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xcbe2,0xf50f, 0xe39c,0x392b, 0xa678,0x3368 + .short 0xd178,0xf073, 0xe182,0x39db, 0xa5ed,0x3179 + .short 0xd74e,0xebed, 0xdf6d,0x3a82, 0xa599,0x2f6c + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xe39c,0xe33a, 0xdb52,0x3bb6, 0xa599,0x2afb + .short 0xea02,0xdf19, 0xd94d,0x3c42, 0xa5ed,0x289a + .short 0xf087,0xdb26, 0xd74e,0x3cc5, 0xa678,0x2620 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0xfdc7,0xd3df, 0xd363,0x3daf, 0xa834,0x20e7 + .short 0x0471,0xd094, 0xd178,0x3e15, 0xa963,0x1e2b + .short 0x0b14,0xcd8c, 0xcf94,0x3e72, 0xaac8,0x1b5d + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x1824,0xc850, 0xcbe2,0x3f0f, 0xae2e,0x1590 + .short 0x1e7e,0xc625, 0xca15,0x3f4f, 0xb02d,0x1294 + .short 0x24ae,0xc44a, 0xc851,0x3f85, 0xb25e,0x0f8d + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + .short 0x306c,0xc18e, 0xc4e2,0x3fd4, 0xb74d,0x0964 + .short 0x35eb,0xc0b1, 0xc338,0x3fec, 0xba09,0x0646 + .short 0x3b1e,0xc02c, 0xc197,0x3ffb, 0xbcf0,0x0324 + + +.end +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F1/libraries/stm_fft/cr4_fft_64_stm32.asm b/STM32F1/libraries/stm_fft/cr4_fft_64_stm32.asm new file mode 100644 index 0000000..bff4548 --- /dev/null +++ b/STM32F1/libraries/stm_fft/cr4_fft_64_stm32.asm @@ -0,0 +1,249 @@ +/*;******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +;* File Name : cr4_fft_64_stm32.s +;* Author : MCD Application Team +;* Version : V2.0.0 +;* Date : 04/27/2009 +;* Description : Optimized 64-point radix-4 complex FFT for Cortex-M3 +;******************************************************************************** +;* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +;* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +;* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +;* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +;* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +;* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +;*******************************************************************************/ + +.cpu cortex-m3 +.fpu softvfp +.syntax unified +.thumb +.text + +.global cr4_fft_64_stm32 +.extern TableFFT + +.equ NPT, 64 + + +/*;******************************************************************************* +;* Function Name : cr4_fft_64_stm32 +;* Description : complex radix-4 64 points FFT +;* Input : - R0 = pssOUT: Output array . +;* - R1 = pssIN: Input array +;* - R2 = Nbin: =64 number of points, this optimized FFT function +;* can only convert 64 points. +;* Output : None +;* Return : None +;********************************************************************************/ +.thumb_func +cr4_fft_64_stm32: + + STMFD SP!, {R4-R11, LR} + + MOV r12, #0 + MOV r3, r0 + MOV r0,#0 + +preloop_v7: + ADD r14, r1, r12, LSR#26 + + LDRSH r5, [r14, #2] + LDRSH r4, [r14],#NPT + LDRSH r9, [r14, #2] + LDRSH r8, [r14],#NPT + LDRSH r7, [r14, #2] + LDRSH r6, [r14],#NPT + LDRSH r11, [r14, #2] + LDRSH r10, [r14],#NPT + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#2 + ADD r5, r5, r7, ASR#2 + SUB r6, r4, r6, ASR#1 + SUB r7, r5, r7, ASR#1 + + ADD r4, r4, r8, ASR#2 + ADD r5, r5, r9, ASR#2 + SUB r8, r4, r8, ASR#1 + SUB r9, r5, r9, ASR#1 + + ADD r6, r6, r11, ASR#2 + SUB r7, r7, r10, ASR#2 + SUB r11, r6, r11, ASR#1 + ADD r10, r7, r10, ASR#1 + + STRH r5, [r3, #2] + STRH r4, [r3], #4 + STRH r7, [r3, #2] + STRH r6, [r3], #4 + STRH r9, [r3, #2] + STRH r8, [r3], #4 + STRH r10, [r3, #2] + STRH r11, [r3], #4 + + ADD r0, r0, #1 + + RBIT r12, r0 + + CMP r0,#16 + BNE preloop_v7 + + SUB r1, r3, r2, LSL#2 + MOV r0, #16 + MOVS r2, r2, LSR#4 + +/*;------------------------------------------------------------------------------ +; The FFT coefficients table can be stored into Flash or RAM. +; The following two lines of code allow selecting the method for coefficients +; storage. +; In the case of choosing coefficients in RAM, you have to: +; 1. Include the file table_fft.h, which is a part of the DSP library, +; in your main file. +; 2. Decomment the line LDR.W pssK, =TableFFT and comment the line +; ADRL pssK, TableFFT_V7 +; 3. Comment all the TableFFT_V7 data. +;------------------------------------------------------------------------------*/ + ADR r3, TableFFT_V7 + /*LDR.W r3, =TableFFT*/ + + +passloop_v7: + STMFD SP!, {r1,r2} + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + SUB r2, r2, #1<<16 + +grouploop_v7: + ADD r2,r2,r0,LSL#(16-2) + +butterloop_v7: + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r11, [r3, #2] + LDRSH r10, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r11 + ADD r14, r10, r11, LSL#1 + MLA r11, r5, r10, r12 + MLA r10, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r9, [r3, #2] + LDRSH r8, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r9 + ADD r14, r8, r9, LSL#1 + MLA r9, r5, r8, r12 + MLA r8, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + SUB r1, r1, r0 + + LDRSH r7, [r3, #2] + LDRSH r6, [r3] + ADD r3, r3, #4 + + SUB r14, r5, r4 + MUL r12, r14, r7 + ADD r14, r6, r7, LSL#1 + MLA r7, r5, r6, r12 + MLA r6, r4, r14, r12 + + LDRSH r5, [r1, #2] + LDRSH r4, [r1] + + ADD r8, r8, r10 + ADD r9, r9, r11 + SUB r10, r8, r10, LSL#1 + SUB r11, r9, r11, LSL#1 + + MOV r4, r4, ASR#2 + MOV r5, r5, ASR#2 + ADD r4, r4, r6, ASR#(2+14) + ADD r5, r5, r7, ASR#(2+14) + SUB r6, r4, r6, ASR#(1+14) + SUB r7, r5, r7, ASR#(1+14) + + ADD r4, r4, r8, ASR#(2+14) + ADD r5, r5, r9, ASR#(2+14) + SUB r8, r4, r8, ASR#(1+14) + SUB r9, r5, r9, ASR#(1+14) + + ADD r6, r6, r11, ASR#(2+14) + SUB r7, r7, r10, ASR#(2+14) + SUB r11, r6, r11, ASR#(1+14) + ADD r10, r7, r10, ASR#(1+14) + + STRH r5, [r1, #2] + STRH r4, [r1] + ADD r1, r1, r0 + STRH r7, [r1, #2] + STRH r6, [r1] + ADD r1, r1, r0 + STRH r9, [r1, #2] + STRH r8, [r1] + ADD r1, r1, r0 + STRH r10, [r1, #2] + STRH r11, [r1], #4 + SUBS r2,r2, #1<<16 + BGE butterloop_v7 + ADD r12, r0, r0, LSL#1 + ADD r1, r1, r12 + + SUB r2, r2, #1 + MOVS r14, r2, LSL#16 + IT ne + SUBNE r3, r3, r12 + BNE grouploop_v7 + + LDMFD sp!, {r1, r2} + MOV r0,r0,LSL#2 + MOVS r2, r2, LSR#2 + BNE passloop_v7 + LDMFD SP!, {R4-R11, PC} + + +TableFFT_V7: + + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + + .short 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000 + .short 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c + .short 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e + .short 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e + .short 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41 + .short 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537 + .short 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21 + .short 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5 + .short 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000 + .short 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5 + .short 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21 + .short 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537 + .short 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41 + .short 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e + .short 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e + .short 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c + + +.end +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F1/libraries/stm_fft/cr4_fft_stm32.h b/STM32F1/libraries/stm_fft/cr4_fft_stm32.h new file mode 100644 index 0000000..a899430 --- /dev/null +++ b/STM32F1/libraries/stm_fft/cr4_fft_stm32.h @@ -0,0 +1,39 @@ +/* + +x[N] be the time signal samples. To use the FFT functions of the DSP library, the +following conditions must be satisfied: +? All the signal samples must be 32-bit data containing the 16-bit real part followed by the +16-bit imaginary part (in the little Endian order: imaginary_real). + + +*/ + +#ifndef __STM32F10x_DSP_H +#define __STM32F10x_DSP_H +/* + * The assembly files can be modified to use a table in RAM rather than ROM. + * Check the assembly files comments. + * + * #include "table_fft.h" + */ + + +extern "C" { + +/* Radix-4 complex FFT for STM32, in assembly */ +/* 16 points*/ +void cr4_fft_16_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); + +/* 64 points*/ +void cr4_fft_64_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); + +/* 256 points */ +void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); + +/* 1024 points */ +void cr4_fft_1024_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); + + +} + +#endif /* __STM32F10x_DSP_H */ diff --git a/STM32F1/libraries/stm_fft/stm32f10x_DSP_lib.chm b/STM32F1/libraries/stm_fft/stm32f10x_DSP_lib.chm new file mode 100644 index 0000000..a27742d Binary files /dev/null and b/STM32F1/libraries/stm_fft/stm32f10x_DSP_lib.chm differ diff --git a/STM32F1/libraries/stm_fft/table_fft.h b/STM32F1/libraries/stm_fft/table_fft.h new file mode 100644 index 0000000..27d3d39 --- /dev/null +++ b/STM32F1/libraries/stm_fft/table_fft.h @@ -0,0 +1,377 @@ +/** + ****************************************************************************** + * @file STM32F10x_DSP_Lib/inc/table_fft.h + * @author MCD Application Team + * @version V2.0.0 + * @date 04/27/2009 + * @brief Contains the coefficients required for FFT computation. + ****************************************************************************** + * @copy + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2009 STMicroelectronics

+ */ + + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __TABLE_FFT_H +#define __TABLE_FFT_H + +/* Includes ------------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +uint16_t TableFFT[]= {0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000, + 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41, + 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000, + 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41, + 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000, /* N=64 */ + 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c, + 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e, + 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e, + 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41, + 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537, + 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21, + 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5, + 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000, + 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5, + 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21, + 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537, + 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41, + 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e, + 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e, + 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c, + 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000, /* N=256 */ + 0x3b1e,0x04b5, 0x3e69,0x0192, 0x3cc8,0x0324, + 0x35eb,0x0964, 0x3cc8,0x0324, 0x396b,0x0646, + 0x306c,0x0e06, 0x3b1e,0x04b5, 0x35eb,0x0964, + 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c, + 0x24ae,0x1709, 0x37af,0x07d6, 0x2e88,0x0f8d, + 0x1e7e,0x1b5d, 0x35eb,0x0964, 0x2aaa,0x1294, + 0x1824,0x1f8c, 0x341e,0x0af1, 0x26b3,0x1590, + 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e, + 0x0b14,0x2760, 0x306c,0x0e06, 0x1e7e,0x1b5d, + 0x0471,0x2afb, 0x2e88,0x0f8d, 0x1a46,0x1e2b, + 0xfdc7,0x2e5a, 0x2c9d,0x1112, 0x15fe,0x20e7, + 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e, + 0xf087,0x3453, 0x28b2,0x1413, 0x0d48,0x2620, + 0xea02,0x36e5, 0x26b3,0x1590, 0x08df,0x289a, + 0xe39c,0x392b, 0x24ae,0x1709, 0x0471,0x2afb, + 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41, + 0xd74e,0x3cc5, 0x2093,0x19ef, 0xfb8f,0x2f6c, + 0xd178,0x3e15, 0x1e7e,0x1b5d, 0xf721,0x3179, + 0xcbe2,0x3f0f, 0x1c64,0x1cc6, 0xf2b8,0x3368, + 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537, + 0xc197,0x3ffb, 0x1824,0x1f8c, 0xea02,0x36e5, + 0xbcf0,0x3fec, 0x15fe,0x20e7, 0xe5ba,0x3871, + 0xb8a6,0x3f85, 0x13d5,0x223d, 0xe182,0x39db, + 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21, + 0xb140,0x3daf, 0x0f79,0x24da, 0xd94d,0x3c42, + 0xae2e,0x3c42, 0x0d48,0x2620, 0xd556,0x3d3f, + 0xab8e,0x3a82, 0x0b14,0x2760, 0xd178,0x3e15, + 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5, + 0xa7b1,0x3612, 0x06a9,0x29ce, 0xca15,0x3f4f, + 0xa678,0x3368, 0x0471,0x2afb, 0xc695,0x3fb1, + 0xa5bc,0x3076, 0x0239,0x2c21, 0xc338,0x3fec, + 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000, + 0xa5bc,0x29ce, 0xfdc7,0x2e5a, 0xbcf0,0x3fec, + 0xa678,0x2620, 0xfb8f,0x2f6c, 0xba09,0x3fb1, + 0xa7b1,0x223d, 0xf957,0x3076, 0xb74d,0x3f4f, + 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5, + 0xab8e,0x19ef, 0xf4ec,0x3274, 0xb25e,0x3e15, + 0xae2e,0x1590, 0xf2b8,0x3368, 0xb02d,0x3d3f, + 0xb140,0x1112, 0xf087,0x3453, 0xae2e,0x3c42, + 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21, + 0xb8a6,0x07d6, 0xec2b,0x3612, 0xaac8,0x39db, + 0xbcf0,0x0324, 0xea02,0x36e5, 0xa963,0x3871, + 0xc197,0xfe6e, 0xe7dc,0x37b0, 0xa834,0x36e5, + 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537, + 0xcbe2,0xf50f, 0xe39c,0x392b, 0xa678,0x3368, + 0xd178,0xf073, 0xe182,0x39db, 0xa5ed,0x3179, + 0xd74e,0xebed, 0xdf6d,0x3a82, 0xa599,0x2f6c, + 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41, + 0xe39c,0xe33a, 0xdb52,0x3bb6, 0xa599,0x2afb, + 0xea02,0xdf19, 0xd94d,0x3c42, 0xa5ed,0x289a, + 0xf087,0xdb26, 0xd74e,0x3cc5, 0xa678,0x2620, + 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e, + 0xfdc7,0xd3df, 0xd363,0x3daf, 0xa834,0x20e7, + 0x0471,0xd094, 0xd178,0x3e15, 0xa963,0x1e2b, + 0x0b14,0xcd8c, 0xcf94,0x3e72, 0xaac8,0x1b5d, + 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e, + 0x1824,0xc850, 0xcbe2,0x3f0f, 0xae2e,0x1590, + 0x1e7e,0xc625, 0xca15,0x3f4f, 0xb02d,0x1294, + 0x24ae,0xc44a, 0xc851,0x3f85, 0xb25e,0x0f8d, + 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c, + 0x306c,0xc18e, 0xc4e2,0x3fd4, 0xb74d,0x0964, + 0x35eb,0xc0b1, 0xc338,0x3fec, 0xba09,0x0646, + 0x3b1e,0xc02c, 0xc197,0x3ffb, 0xbcf0,0x0324, + 0x4000,0x0000, 0x4000,0x0000, 0x4000,0x0000, /* N=1024*/ + 0x3ed0,0x012e, 0x3f9b,0x0065, 0x3f36,0x00c9, + 0x3d9a,0x025b, 0x3f36,0x00c9, 0x3e69,0x0192, + 0x3c5f,0x0388, 0x3ed0,0x012e, 0x3d9a,0x025b, + 0x3b1e,0x04b5, 0x3e69,0x0192, 0x3cc8,0x0324, + 0x39d9,0x05e2, 0x3e02,0x01f7, 0x3bf4,0x03ed, + 0x388e,0x070e, 0x3d9a,0x025b, 0x3b1e,0x04b5, + 0x373f,0x0839, 0x3d31,0x02c0, 0x3a46,0x057e, + 0x35eb,0x0964, 0x3cc8,0x0324, 0x396b,0x0646, + 0x3492,0x0a8e, 0x3c5f,0x0388, 0x388e,0x070e, + 0x3334,0x0bb7, 0x3bf4,0x03ed, 0x37af,0x07d6, + 0x31d2,0x0cdf, 0x3b8a,0x0451, 0x36ce,0x089d, + 0x306c,0x0e06, 0x3b1e,0x04b5, 0x35eb,0x0964, + 0x2f02,0x0f2b, 0x3ab2,0x051a, 0x3505,0x0a2b, + 0x2d93,0x1050, 0x3a46,0x057e, 0x341e,0x0af1, + 0x2c21,0x1173, 0x39d9,0x05e2, 0x3334,0x0bb7, + 0x2aaa,0x1294, 0x396b,0x0646, 0x3249,0x0c7c, + 0x2931,0x13b4, 0x38fd,0x06aa, 0x315b,0x0d41, + 0x27b3,0x14d2, 0x388e,0x070e, 0x306c,0x0e06, + 0x2632,0x15ee, 0x381f,0x0772, 0x2f7b,0x0eca, + 0x24ae,0x1709, 0x37af,0x07d6, 0x2e88,0x0f8d, + 0x2326,0x1821, 0x373f,0x0839, 0x2d93,0x1050, + 0x219c,0x1937, 0x36ce,0x089d, 0x2c9d,0x1112, + 0x200e,0x1a4b, 0x365d,0x0901, 0x2ba4,0x11d3, + 0x1e7e,0x1b5d, 0x35eb,0x0964, 0x2aaa,0x1294, + 0x1ceb,0x1c6c, 0x3578,0x09c7, 0x29af,0x1354, + 0x1b56,0x1d79, 0x3505,0x0a2b, 0x28b2,0x1413, + 0x19be,0x1e84, 0x3492,0x0a8e, 0x27b3,0x14d2, + 0x1824,0x1f8c, 0x341e,0x0af1, 0x26b3,0x1590, + 0x1688,0x2091, 0x33a9,0x0b54, 0x25b1,0x164c, + 0x14ea,0x2193, 0x3334,0x0bb7, 0x24ae,0x1709, + 0x134a,0x2292, 0x32bf,0x0c1a, 0x23a9,0x17c4, + 0x11a8,0x238e, 0x3249,0x0c7c, 0x22a3,0x187e, + 0x1005,0x2488, 0x31d2,0x0cdf, 0x219c,0x1937, + 0x0e61,0x257e, 0x315b,0x0d41, 0x2093,0x19ef, + 0x0cbb,0x2671, 0x30e4,0x0da4, 0x1f89,0x1aa7, + 0x0b14,0x2760, 0x306c,0x0e06, 0x1e7e,0x1b5d, + 0x096d,0x284c, 0x2ff4,0x0e68, 0x1d72,0x1c12, + 0x07c4,0x2935, 0x2f7b,0x0eca, 0x1c64,0x1cc6, + 0x061b,0x2a1a, 0x2f02,0x0f2b, 0x1b56,0x1d79, + 0x0471,0x2afb, 0x2e88,0x0f8d, 0x1a46,0x1e2b, + 0x02c7,0x2bd8, 0x2e0e,0x0fee, 0x1935,0x1edc, + 0x011c,0x2cb2, 0x2d93,0x1050, 0x1824,0x1f8c, + 0xff72,0x2d88, 0x2d18,0x10b1, 0x1711,0x203a, + 0xfdc7,0x2e5a, 0x2c9d,0x1112, 0x15fe,0x20e7, + 0xfc1d,0x2f28, 0x2c21,0x1173, 0x14ea,0x2193, + 0xfa73,0x2ff2, 0x2ba4,0x11d3, 0x13d5,0x223d, + 0xf8ca,0x30b8, 0x2b28,0x1234, 0x12bf,0x22e7, + 0xf721,0x3179, 0x2aaa,0x1294, 0x11a8,0x238e, + 0xf579,0x3236, 0x2a2d,0x12f4, 0x1091,0x2435, + 0xf3d2,0x32ef, 0x29af,0x1354, 0x0f79,0x24da, + 0xf22c,0x33a3, 0x2931,0x13b4, 0x0e61,0x257e, + 0xf087,0x3453, 0x28b2,0x1413, 0x0d48,0x2620, + 0xeee3,0x34ff, 0x2833,0x1473, 0x0c2e,0x26c1, + 0xed41,0x35a5, 0x27b3,0x14d2, 0x0b14,0x2760, + 0xeba1,0x3648, 0x2733,0x1531, 0x09fa,0x27fe, + 0xea02,0x36e5, 0x26b3,0x1590, 0x08df,0x289a, + 0xe865,0x377e, 0x2632,0x15ee, 0x07c4,0x2935, + 0xe6cb,0x3812, 0x25b1,0x164c, 0x06a9,0x29ce, + 0xe532,0x38a1, 0x252f,0x16ab, 0x058d,0x2a65, + 0xe39c,0x392b, 0x24ae,0x1709, 0x0471,0x2afb, + 0xe208,0x39b0, 0x242b,0x1766, 0x0355,0x2b8f, + 0xe077,0x3a30, 0x23a9,0x17c4, 0x0239,0x2c21, + 0xdee9,0x3aab, 0x2326,0x1821, 0x011c,0x2cb2, + 0xdd5d,0x3b21, 0x22a3,0x187e, 0x0000,0x2d41, + 0xdbd5,0x3b92, 0x221f,0x18db, 0xfee4,0x2dcf, + 0xda4f,0x3bfd, 0x219c,0x1937, 0xfdc7,0x2e5a, + 0xd8cd,0x3c64, 0x2117,0x1993, 0xfcab,0x2ee4, + 0xd74e,0x3cc5, 0x2093,0x19ef, 0xfb8f,0x2f6c, + 0xd5d3,0x3d21, 0x200e,0x1a4b, 0xfa73,0x2ff2, + 0xd45c,0x3d78, 0x1f89,0x1aa7, 0xf957,0x3076, + 0xd2e8,0x3dc9, 0x1f04,0x1b02, 0xf83c,0x30f9, + 0xd178,0x3e15, 0x1e7e,0x1b5d, 0xf721,0x3179, + 0xd00c,0x3e5c, 0x1df8,0x1bb8, 0xf606,0x31f8, + 0xcea5,0x3e9d, 0x1d72,0x1c12, 0xf4ec,0x3274, + 0xcd41,0x3ed8, 0x1ceb,0x1c6c, 0xf3d2,0x32ef, + 0xcbe2,0x3f0f, 0x1c64,0x1cc6, 0xf2b8,0x3368, + 0xca88,0x3f40, 0x1bdd,0x1d20, 0xf19f,0x33df, + 0xc932,0x3f6b, 0x1b56,0x1d79, 0xf087,0x3453, + 0xc7e1,0x3f91, 0x1ace,0x1dd3, 0xef6f,0x34c6, + 0xc695,0x3fb1, 0x1a46,0x1e2b, 0xee58,0x3537, + 0xc54e,0x3fcc, 0x19be,0x1e84, 0xed41,0x35a5, + 0xc40c,0x3fe1, 0x1935,0x1edc, 0xec2b,0x3612, + 0xc2cf,0x3ff1, 0x18ad,0x1f34, 0xeb16,0x367d, + 0xc197,0x3ffb, 0x1824,0x1f8c, 0xea02,0x36e5, + 0xc065,0x4000, 0x179b,0x1fe3, 0xe8ef,0x374b, + 0xbf38,0x3fff, 0x1711,0x203a, 0xe7dc,0x37b0, + 0xbe11,0x3ff8, 0x1688,0x2091, 0xe6cb,0x3812, + 0xbcf0,0x3fec, 0x15fe,0x20e7, 0xe5ba,0x3871, + 0xbbd4,0x3fdb, 0x1574,0x213d, 0xe4aa,0x38cf, + 0xbabf,0x3fc4, 0x14ea,0x2193, 0xe39c,0x392b, + 0xb9af,0x3fa7, 0x145f,0x21e8, 0xe28e,0x3984, + 0xb8a6,0x3f85, 0x13d5,0x223d, 0xe182,0x39db, + 0xb7a2,0x3f5d, 0x134a,0x2292, 0xe077,0x3a30, + 0xb6a5,0x3f30, 0x12bf,0x22e7, 0xdf6d,0x3a82, + 0xb5af,0x3efd, 0x1234,0x233b, 0xde64,0x3ad3, + 0xb4be,0x3ec5, 0x11a8,0x238e, 0xdd5d,0x3b21, + 0xb3d5,0x3e88, 0x111d,0x23e2, 0xdc57,0x3b6d, + 0xb2f2,0x3e45, 0x1091,0x2435, 0xdb52,0x3bb6, + 0xb215,0x3dfc, 0x1005,0x2488, 0xda4f,0x3bfd, + 0xb140,0x3daf, 0x0f79,0x24da, 0xd94d,0x3c42, + 0xb071,0x3d5b, 0x0eed,0x252c, 0xd84d,0x3c85, + 0xafa9,0x3d03, 0x0e61,0x257e, 0xd74e,0x3cc5, + 0xaee8,0x3ca5, 0x0dd4,0x25cf, 0xd651,0x3d03, + 0xae2e,0x3c42, 0x0d48,0x2620, 0xd556,0x3d3f, + 0xad7b,0x3bda, 0x0cbb,0x2671, 0xd45c,0x3d78, + 0xacd0,0x3b6d, 0x0c2e,0x26c1, 0xd363,0x3daf, + 0xac2b,0x3afa, 0x0ba1,0x2711, 0xd26d,0x3de3, + 0xab8e,0x3a82, 0x0b14,0x2760, 0xd178,0x3e15, + 0xaaf8,0x3a06, 0x0a87,0x27af, 0xd085,0x3e45, + 0xaa6a,0x3984, 0x09fa,0x27fe, 0xcf94,0x3e72, + 0xa9e3,0x38fd, 0x096d,0x284c, 0xcea5,0x3e9d, + 0xa963,0x3871, 0x08df,0x289a, 0xcdb7,0x3ec5, + 0xa8eb,0x37e1, 0x0852,0x28e7, 0xcccc,0x3eeb, + 0xa87b,0x374b, 0x07c4,0x2935, 0xcbe2,0x3f0f, + 0xa812,0x36b1, 0x0736,0x2981, 0xcafb,0x3f30, + 0xa7b1,0x3612, 0x06a9,0x29ce, 0xca15,0x3f4f, + 0xa757,0x356e, 0x061b,0x2a1a, 0xc932,0x3f6b, + 0xa705,0x34c6, 0x058d,0x2a65, 0xc851,0x3f85, + 0xa6bb,0x3419, 0x04ff,0x2ab0, 0xc772,0x3f9c, + 0xa678,0x3368, 0x0471,0x2afb, 0xc695,0x3fb1, + 0xa63e,0x32b2, 0x03e3,0x2b45, 0xc5ba,0x3fc4, + 0xa60b,0x31f8, 0x0355,0x2b8f, 0xc4e2,0x3fd4, + 0xa5e0,0x3139, 0x02c7,0x2bd8, 0xc40c,0x3fe1, + 0xa5bc,0x3076, 0x0239,0x2c21, 0xc338,0x3fec, + 0xa5a1,0x2faf, 0x01aa,0x2c6a, 0xc266,0x3ff5, + 0xa58d,0x2ee4, 0x011c,0x2cb2, 0xc197,0x3ffb, + 0xa581,0x2e15, 0x008e,0x2cfa, 0xc0ca,0x3fff, + 0xa57e,0x2d41, 0x0000,0x2d41, 0xc000,0x4000, + 0xa581,0x2c6a, 0xff72,0x2d88, 0xbf38,0x3fff, + 0xa58d,0x2b8f, 0xfee4,0x2dcf, 0xbe73,0x3ffb, + 0xa5a1,0x2ab0, 0xfe56,0x2e15, 0xbdb0,0x3ff5, + 0xa5bc,0x29ce, 0xfdc7,0x2e5a, 0xbcf0,0x3fec, + 0xa5e0,0x28e7, 0xfd39,0x2e9f, 0xbc32,0x3fe1, + 0xa60b,0x27fe, 0xfcab,0x2ee4, 0xbb77,0x3fd4, + 0xa63e,0x2711, 0xfc1d,0x2f28, 0xbabf,0x3fc4, + 0xa678,0x2620, 0xfb8f,0x2f6c, 0xba09,0x3fb1, + 0xa6bb,0x252c, 0xfb01,0x2faf, 0xb956,0x3f9c, + 0xa705,0x2435, 0xfa73,0x2ff2, 0xb8a6,0x3f85, + 0xa757,0x233b, 0xf9e5,0x3034, 0xb7f8,0x3f6b, + 0xa7b1,0x223d, 0xf957,0x3076, 0xb74d,0x3f4f, + 0xa812,0x213d, 0xf8ca,0x30b8, 0xb6a5,0x3f30, + 0xa87b,0x203a, 0xf83c,0x30f9, 0xb600,0x3f0f, + 0xa8eb,0x1f34, 0xf7ae,0x3139, 0xb55e,0x3eeb, + 0xa963,0x1e2b, 0xf721,0x3179, 0xb4be,0x3ec5, + 0xa9e3,0x1d20, 0xf693,0x31b9, 0xb422,0x3e9d, + 0xaa6a,0x1c12, 0xf606,0x31f8, 0xb388,0x3e72, + 0xaaf8,0x1b02, 0xf579,0x3236, 0xb2f2,0x3e45, + 0xab8e,0x19ef, 0xf4ec,0x3274, 0xb25e,0x3e15, + 0xac2b,0x18db, 0xf45f,0x32b2, 0xb1cd,0x3de3, + 0xacd0,0x17c4, 0xf3d2,0x32ef, 0xb140,0x3daf, + 0xad7b,0x16ab, 0xf345,0x332c, 0xb0b5,0x3d78, + 0xae2e,0x1590, 0xf2b8,0x3368, 0xb02d,0x3d3f, + 0xaee8,0x1473, 0xf22c,0x33a3, 0xafa9,0x3d03, + 0xafa9,0x1354, 0xf19f,0x33df, 0xaf28,0x3cc5, + 0xb071,0x1234, 0xf113,0x3419, 0xaea9,0x3c85, + 0xb140,0x1112, 0xf087,0x3453, 0xae2e,0x3c42, + 0xb215,0x0fee, 0xeffb,0x348d, 0xadb6,0x3bfd, + 0xb2f2,0x0eca, 0xef6f,0x34c6, 0xad41,0x3bb6, + 0xb3d5,0x0da4, 0xeee3,0x34ff, 0xacd0,0x3b6d, + 0xb4be,0x0c7c, 0xee58,0x3537, 0xac61,0x3b21, + 0xb5af,0x0b54, 0xedcc,0x356e, 0xabf6,0x3ad3, + 0xb6a5,0x0a2b, 0xed41,0x35a5, 0xab8e,0x3a82, + 0xb7a2,0x0901, 0xecb6,0x35dc, 0xab29,0x3a30, + 0xb8a6,0x07d6, 0xec2b,0x3612, 0xaac8,0x39db, + 0xb9af,0x06aa, 0xeba1,0x3648, 0xaa6a,0x3984, + 0xbabf,0x057e, 0xeb16,0x367d, 0xaa0f,0x392b, + 0xbbd4,0x0451, 0xea8c,0x36b1, 0xa9b7,0x38cf, + 0xbcf0,0x0324, 0xea02,0x36e5, 0xa963,0x3871, + 0xbe11,0x01f7, 0xe978,0x3718, 0xa912,0x3812, + 0xbf38,0x00c9, 0xe8ef,0x374b, 0xa8c5,0x37b0, + 0xc065,0xff9b, 0xe865,0x377e, 0xa87b,0x374b, + 0xc197,0xfe6e, 0xe7dc,0x37b0, 0xa834,0x36e5, + 0xc2cf,0xfd40, 0xe753,0x37e1, 0xa7f1,0x367d, + 0xc40c,0xfc13, 0xe6cb,0x3812, 0xa7b1,0x3612, + 0xc54e,0xfae6, 0xe642,0x3842, 0xa774,0x35a5, + 0xc695,0xf9ba, 0xe5ba,0x3871, 0xa73b,0x3537, + 0xc7e1,0xf88e, 0xe532,0x38a1, 0xa705,0x34c6, + 0xc932,0xf763, 0xe4aa,0x38cf, 0xa6d3,0x3453, + 0xca88,0xf639, 0xe423,0x38fd, 0xa6a4,0x33df, + 0xcbe2,0xf50f, 0xe39c,0x392b, 0xa678,0x3368, + 0xcd41,0xf3e6, 0xe315,0x3958, 0xa650,0x32ef, + 0xcea5,0xf2bf, 0xe28e,0x3984, 0xa62c,0x3274, + 0xd00c,0xf198, 0xe208,0x39b0, 0xa60b,0x31f8, + 0xd178,0xf073, 0xe182,0x39db, 0xa5ed,0x3179, + 0xd2e8,0xef4f, 0xe0fc,0x3a06, 0xa5d3,0x30f9, + 0xd45c,0xee2d, 0xe077,0x3a30, 0xa5bc,0x3076, + 0xd5d3,0xed0c, 0xdff2,0x3a59, 0xa5a9,0x2ff2, + 0xd74e,0xebed, 0xdf6d,0x3a82, 0xa599,0x2f6c, + 0xd8cd,0xeacf, 0xdee9,0x3aab, 0xa58d,0x2ee4, + 0xda4f,0xe9b4, 0xde64,0x3ad3, 0xa585,0x2e5a, + 0xdbd5,0xe89a, 0xdde1,0x3afa, 0xa57f,0x2dcf, + 0xdd5d,0xe782, 0xdd5d,0x3b21, 0xa57e,0x2d41, + 0xdee9,0xe66d, 0xdcda,0x3b47, 0xa57f,0x2cb2, + 0xe077,0xe559, 0xdc57,0x3b6d, 0xa585,0x2c21, + 0xe208,0xe448, 0xdbd5,0x3b92, 0xa58d,0x2b8f, + 0xe39c,0xe33a, 0xdb52,0x3bb6, 0xa599,0x2afb, + 0xe532,0xe22d, 0xdad1,0x3bda, 0xa5a9,0x2a65, + 0xe6cb,0xe124, 0xda4f,0x3bfd, 0xa5bc,0x29ce, + 0xe865,0xe01d, 0xd9ce,0x3c20, 0xa5d3,0x2935, + 0xea02,0xdf19, 0xd94d,0x3c42, 0xa5ed,0x289a, + 0xeba1,0xde18, 0xd8cd,0x3c64, 0xa60b,0x27fe, + 0xed41,0xdd19, 0xd84d,0x3c85, 0xa62c,0x2760, + 0xeee3,0xdc1e, 0xd7cd,0x3ca5, 0xa650,0x26c1, + 0xf087,0xdb26, 0xd74e,0x3cc5, 0xa678,0x2620, + 0xf22c,0xda31, 0xd6cf,0x3ce4, 0xa6a4,0x257e, + 0xf3d2,0xd93f, 0xd651,0x3d03, 0xa6d3,0x24da, + 0xf579,0xd851, 0xd5d3,0x3d21, 0xa705,0x2435, + 0xf721,0xd766, 0xd556,0x3d3f, 0xa73b,0x238e, + 0xf8ca,0xd67f, 0xd4d8,0x3d5b, 0xa774,0x22e7, + 0xfa73,0xd59b, 0xd45c,0x3d78, 0xa7b1,0x223d, + 0xfc1d,0xd4bb, 0xd3df,0x3d93, 0xa7f1,0x2193, + 0xfdc7,0xd3df, 0xd363,0x3daf, 0xa834,0x20e7, + 0xff72,0xd306, 0xd2e8,0x3dc9, 0xa87b,0x203a, + 0x011c,0xd231, 0xd26d,0x3de3, 0xa8c5,0x1f8c, + 0x02c7,0xd161, 0xd1f2,0x3dfc, 0xa912,0x1edc, + 0x0471,0xd094, 0xd178,0x3e15, 0xa963,0x1e2b, + 0x061b,0xcfcc, 0xd0fe,0x3e2d, 0xa9b7,0x1d79, + 0x07c4,0xcf07, 0xd085,0x3e45, 0xaa0f,0x1cc6, + 0x096d,0xce47, 0xd00c,0x3e5c, 0xaa6a,0x1c12, + 0x0b14,0xcd8c, 0xcf94,0x3e72, 0xaac8,0x1b5d, + 0x0cbb,0xccd4, 0xcf1c,0x3e88, 0xab29,0x1aa7, + 0x0e61,0xcc21, 0xcea5,0x3e9d, 0xab8e,0x19ef, + 0x1005,0xcb73, 0xce2e,0x3eb1, 0xabf6,0x1937, + 0x11a8,0xcac9, 0xcdb7,0x3ec5, 0xac61,0x187e, + 0x134a,0xca24, 0xcd41,0x3ed8, 0xacd0,0x17c4, + 0x14ea,0xc983, 0xcccc,0x3eeb, 0xad41,0x1709, + 0x1688,0xc8e8, 0xcc57,0x3efd, 0xadb6,0x164c, + 0x1824,0xc850, 0xcbe2,0x3f0f, 0xae2e,0x1590, + 0x19be,0xc7be, 0xcb6e,0x3f20, 0xaea9,0x14d2, + 0x1b56,0xc731, 0xcafb,0x3f30, 0xaf28,0x1413, + 0x1ceb,0xc6a8, 0xca88,0x3f40, 0xafa9,0x1354, + 0x1e7e,0xc625, 0xca15,0x3f4f, 0xb02d,0x1294, + 0x200e,0xc5a7, 0xc9a3,0x3f5d, 0xb0b5,0x11d3, + 0x219c,0xc52d, 0xc932,0x3f6b, 0xb140,0x1112, + 0x2326,0xc4b9, 0xc8c1,0x3f78, 0xb1cd,0x1050, + 0x24ae,0xc44a, 0xc851,0x3f85, 0xb25e,0x0f8d, + 0x2632,0xc3e0, 0xc7e1,0x3f91, 0xb2f2,0x0eca, + 0x27b3,0xc37b, 0xc772,0x3f9c, 0xb388,0x0e06, + 0x2931,0xc31c, 0xc703,0x3fa7, 0xb422,0x0d41, + 0x2aaa,0xc2c1, 0xc695,0x3fb1, 0xb4be,0x0c7c, + 0x2c21,0xc26d, 0xc627,0x3fbb, 0xb55e,0x0bb7, + 0x2d93,0xc21d, 0xc5ba,0x3fc4, 0xb600,0x0af1, + 0x2f02,0xc1d3, 0xc54e,0x3fcc, 0xb6a5,0x0a2b, + 0x306c,0xc18e, 0xc4e2,0x3fd4, 0xb74d,0x0964, + 0x31d2,0xc14f, 0xc476,0x3fdb, 0xb7f8,0x089d, + 0x3334,0xc115, 0xc40c,0x3fe1, 0xb8a6,0x07d6, + 0x3492,0xc0e0, 0xc3a1,0x3fe7, 0xb956,0x070e, + 0x35eb,0xc0b1, 0xc338,0x3fec, 0xba09,0x0646, + 0x373f,0xc088, 0xc2cf,0x3ff1, 0xbabf,0x057e, + 0x388e,0xc064, 0xc266,0x3ff5, 0xbb77,0x04b5, + 0x39d9,0xc045, 0xc1fe,0x3ff8, 0xbc32,0x03ed, + 0x3b1e,0xc02c, 0xc197,0x3ffb, 0xbcf0,0x0324, + 0x3c5f,0xc019, 0xc130,0x3ffd, 0xbdb0,0x025b, + 0x3d9a,0xc00b, 0xc0ca,0x3fff, 0xbe73,0x0192, + 0x3ed0,0xc003, 0xc065,0x4000, 0xbf38,0x00c9 +}; + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +#endif /* __TABLE_FFT_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F1/platform.txt b/STM32F1/platform.txt index 3ffde2e..418ad28 100644 --- a/STM32F1/platform.txt +++ b/STM32F1/platform.txt @@ -16,27 +16,27 @@ compiler.warning_flags.all=-Wall -Wextra -DDEBUG_LEVEL=DEBUG_ALL # ---------------------- compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/ compiler.c.cmd=arm-none-eabi-gcc -compiler.c.flags=-c -g -Os {compiler.warning_flags} -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.c.flags=-c -g {build.flags.optimize} {compiler.warning_flags} -std=gnu11 -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} compiler.c.elf.cmd=arm-none-eabi-g++ -compiler.c.elf.flags=-Os -Wl,--gc-sections +compiler.c.elf.flags={build.flags.optimize} -Wl,--gc-sections {build.flags.ldspecs} compiler.S.cmd=arm-none-eabi-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD compiler.cpp.cmd=arm-none-eabi-g++ -compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.cpp.flags=-c -g {build.flags.optimize} {compiler.warning_flags} -std=gnu++11 -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} compiler.ar.cmd=arm-none-eabi-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arm-none-eabi-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 compiler.elf2hex.flags=-O binary compiler.elf2hex.cmd=arm-none-eabi-objcopy -compiler.ldflags= +compiler.ldflags={build.flags.ldspecs} compiler.size.cmd=arm-none-eabi-size compiler.define=-DARDUINO= # this can be overriden in boards.txt build.f_cpu=72000000L build.mcu=cortex-m3 -build.common_flags=-mthumb -march=armv7-m -D__STM32F1__ +build.common_flags=-mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 build.variant_system_lib=libmaple.a ## LED stuff is not really used but is still required in the code build.error_led_port=GPIOB @@ -57,7 +57,7 @@ compiler.ar.extra_flags= compiler.elf2hex.extra_flags= -compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" +compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" @@ -87,7 +87,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mcpu={b recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} "{build.path}/{archive_file}" -Wl,--end-group +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} "{archive_file_path}" -Wl,--end-group ## Create eeprom recipe.objcopy.eep.pattern= @@ -161,3 +161,15 @@ tools.jlink_upload.path.linux64={runtime.hardware.path}/tools/linux64 tools.jlink_upload.upload.params.verbose=-d tools.jlink_upload.upload.params.quiet=n tools.jlink_upload.upload.pattern="{path}/{cmd}" "{build.path}/{build.project_name}.bin" + +# HID upload +tools.hid_upload.cmd=hid_upload +tools.hid_upload.cmd.windows=hid_upload.bat +tools.hid_upload.cmd.macosx=hid_upload +tools.hid_upload.path={runtime.hardware.path}/tools/win +tools.hid_upload.path.macosx={runtime.hardware.path}/tools/macosx +tools.hid_upload.path.linux={runtime.hardware.path}/tools/linux +tools.hid_upload.path.linux64={runtime.hardware.path}/tools/linux64 +tools.hid_upload.upload.params.verbose=-d +tools.hid_upload.upload.params.quiet=n +tools.hid_upload.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" \ No newline at end of file diff --git a/STM32F1/system/libmaple/dma_private.h b/STM32F1/system/libmaple/dma_private.h index f3765fc..063d157 100644 --- a/STM32F1/system/libmaple/dma_private.h +++ b/STM32F1/system/libmaple/dma_private.h @@ -57,6 +57,6 @@ enum dma_atype { DMA_ATYPE_OTHER, }; -enum dma_atype _dma_addr_type(__io void *addr); +enum dma_atype _dma_addr_type(__IO void *addr); #endif diff --git a/STM32F1/system/libmaple/exti_private.h b/STM32F1/system/libmaple/exti_private.h index 4f0a4cf..221cae4 100644 --- a/STM32F1/system/libmaple/exti_private.h +++ b/STM32F1/system/libmaple/exti_private.h @@ -29,6 +29,6 @@ #include -void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port); +void exti_do_select(__IO uint32 *exti_cr, exti_num num, exti_cfg port); #endif diff --git a/STM32F1/system/libmaple/include/libmaple/adc.h b/STM32F1/system/libmaple/include/libmaple/adc.h index 21efaf5..9190099 100644 --- a/STM32F1/system/libmaple/include/libmaple/adc.h +++ b/STM32F1/system/libmaple/include/libmaple/adc.h @@ -52,26 +52,26 @@ extern "C"{ /** ADC register map type. */ typedef struct adc_reg_map { - __io uint32 SR; ///< Status register - __io uint32 CR1; ///< Control register 1 - __io uint32 CR2; ///< Control register 2 - __io uint32 SMPR1; ///< Sample time register 1 - __io uint32 SMPR2; ///< Sample time register 2 - __io uint32 JOFR1; ///< Injected channel data offset register 1 - __io uint32 JOFR2; ///< Injected channel data offset register 2 - __io uint32 JOFR3; ///< Injected channel data offset register 3 - __io uint32 JOFR4; ///< Injected channel data offset register 4 - __io uint32 HTR; ///< Watchdog high threshold register - __io uint32 LTR; ///< Watchdog low threshold register - __io uint32 SQR1; ///< Regular sequence register 1 - __io uint32 SQR2; ///< Regular sequence register 2 - __io uint32 SQR3; ///< Regular sequence register 3 - __io uint32 JSQR; ///< Injected sequence register - __io uint32 JDR1; ///< Injected data register 1 - __io uint32 JDR2; ///< Injected data register 2 - __io uint32 JDR3; ///< Injected data register 3 - __io uint32 JDR4; ///< Injected data register 4 - __io uint32 DR; ///< Regular data register + __IO uint32 SR; ///< Status register + __IO uint32 CR1; ///< Control register 1 + __IO uint32 CR2; ///< Control register 2 + __IO uint32 SMPR1; ///< Sample time register 1 + __IO uint32 SMPR2; ///< Sample time register 2 + __IO uint32 JOFR1; ///< Injected channel data offset register 1 + __IO uint32 JOFR2; ///< Injected channel data offset register 2 + __IO uint32 JOFR3; ///< Injected channel data offset register 3 + __IO uint32 JOFR4; ///< Injected channel data offset register 4 + __IO uint32 HTR; ///< Watchdog high threshold register + __IO uint32 LTR; ///< Watchdog low threshold register + __IO uint32 SQR1; ///< Regular sequence register 1 + __IO uint32 SQR2; ///< Regular sequence register 2 + __IO uint32 SQR3; ///< Regular sequence register 3 + __IO uint32 JSQR; ///< Injected sequence register + __IO uint32 JDR1; ///< Injected data register 1 + __IO uint32 JDR2; ///< Injected data register 2 + __IO uint32 JDR3; ///< Injected data register 3 + __IO uint32 JDR4; ///< Injected data register 4 + __IO uint32 DR; ///< Regular data register } adc_reg_map; diff --git a/STM32F1/system/libmaple/include/libmaple/bkp.h b/STM32F1/system/libmaple/include/libmaple/bkp.h index bb63a2f..f57235a 100644 --- a/STM32F1/system/libmaple/include/libmaple/bkp.h +++ b/STM32F1/system/libmaple/include/libmaple/bkp.h @@ -47,54 +47,54 @@ extern "C" { /** Backup peripheral register map type. */ typedef struct bkp_reg_map { const uint32 RESERVED1; ///< Reserved - __io uint32 DR1; ///< Data register 1 - __io uint32 DR2; ///< Data register 2 - __io uint32 DR3; ///< Data register 3 - __io uint32 DR4; ///< Data register 4 - __io uint32 DR5; ///< Data register 5 - __io uint32 DR6; ///< Data register 6 - __io uint32 DR7; ///< Data register 7 - __io uint32 DR8; ///< Data register 8 - __io uint32 DR9; ///< Data register 9 - __io uint32 DR10; ///< Data register 10 - __io uint32 RTCCR; ///< RTC control register - __io uint32 CR; ///< Control register - __io uint32 CSR; ///< Control and status register + __IO uint32 DR1; ///< Data register 1 + __IO uint32 DR2; ///< Data register 2 + __IO uint32 DR3; ///< Data register 3 + __IO uint32 DR4; ///< Data register 4 + __IO uint32 DR5; ///< Data register 5 + __IO uint32 DR6; ///< Data register 6 + __IO uint32 DR7; ///< Data register 7 + __IO uint32 DR8; ///< Data register 8 + __IO uint32 DR9; ///< Data register 9 + __IO uint32 DR10; ///< Data register 10 + __IO uint32 RTCCR; ///< RTC control register + __IO uint32 CR; ///< Control register + __IO uint32 CSR; ///< Control and status register #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) const uint32 RESERVED2; ///< Reserved const uint32 RESERVED3; ///< Reserved - __io uint32 DR11; ///< Data register 11 - __io uint32 DR12; ///< Data register 12 - __io uint32 DR13; ///< Data register 13 - __io uint32 DR14; ///< Data register 14 - __io uint32 DR15; ///< Data register 15 - __io uint32 DR16; ///< Data register 16 - __io uint32 DR17; ///< Data register 17 - __io uint32 DR18; ///< Data register 18 - __io uint32 DR19; ///< Data register 19 - __io uint32 DR20; ///< Data register 20 - __io uint32 DR21; ///< Data register 21 - __io uint32 DR22; ///< Data register 22 - __io uint32 DR23; ///< Data register 23 - __io uint32 DR24; ///< Data register 24 - __io uint32 DR25; ///< Data register 25 - __io uint32 DR26; ///< Data register 26 - __io uint32 DR27; ///< Data register 27 - __io uint32 DR28; ///< Data register 28 - __io uint32 DR29; ///< Data register 29 - __io uint32 DR30; ///< Data register 30 - __io uint32 DR31; ///< Data register 31 - __io uint32 DR32; ///< Data register 32 - __io uint32 DR33; ///< Data register 33 - __io uint32 DR34; ///< Data register 34 - __io uint32 DR35; ///< Data register 35 - __io uint32 DR36; ///< Data register 36 - __io uint32 DR37; ///< Data register 37 - __io uint32 DR38; ///< Data register 38 - __io uint32 DR39; ///< Data register 39 - __io uint32 DR40; ///< Data register 40 - __io uint32 DR41; ///< Data register 41 - __io uint32 DR42; ///< Data register 42 + __IO uint32 DR11; ///< Data register 11 + __IO uint32 DR12; ///< Data register 12 + __IO uint32 DR13; ///< Data register 13 + __IO uint32 DR14; ///< Data register 14 + __IO uint32 DR15; ///< Data register 15 + __IO uint32 DR16; ///< Data register 16 + __IO uint32 DR17; ///< Data register 17 + __IO uint32 DR18; ///< Data register 18 + __IO uint32 DR19; ///< Data register 19 + __IO uint32 DR20; ///< Data register 20 + __IO uint32 DR21; ///< Data register 21 + __IO uint32 DR22; ///< Data register 22 + __IO uint32 DR23; ///< Data register 23 + __IO uint32 DR24; ///< Data register 24 + __IO uint32 DR25; ///< Data register 25 + __IO uint32 DR26; ///< Data register 26 + __IO uint32 DR27; ///< Data register 27 + __IO uint32 DR28; ///< Data register 28 + __IO uint32 DR29; ///< Data register 29 + __IO uint32 DR30; ///< Data register 30 + __IO uint32 DR31; ///< Data register 31 + __IO uint32 DR32; ///< Data register 32 + __IO uint32 DR33; ///< Data register 33 + __IO uint32 DR34; ///< Data register 34 + __IO uint32 DR35; ///< Data register 35 + __IO uint32 DR36; ///< Data register 36 + __IO uint32 DR37; ///< Data register 37 + __IO uint32 DR38; ///< Data register 38 + __IO uint32 DR39; ///< Data register 39 + __IO uint32 DR40; ///< Data register 40 + __IO uint32 DR41; ///< Data register 41 + __IO uint32 DR42; ///< Data register 42 #endif } bkp_reg_map; diff --git a/STM32F1/system/libmaple/include/libmaple/delay.h b/STM32F1/system/libmaple/include/libmaple/delay.h index 472a208..64bb510 100644 --- a/STM32F1/system/libmaple/include/libmaple/delay.h +++ b/STM32F1/system/libmaple/include/libmaple/delay.h @@ -46,6 +46,10 @@ extern "C" { * @param us Number of microseconds to delay. */ static inline void delay_us(uint32 us) { + if (us==0) + { + return; + } us *= STM32_DELAY_US_MULT; /* fudge for function call overhead */ diff --git a/STM32F1/system/libmaple/include/libmaple/dma.h b/STM32F1/system/libmaple/include/libmaple/dma.h index a75b314..87e1840 100644 --- a/STM32F1/system/libmaple/include/libmaple/dma.h +++ b/STM32F1/system/libmaple/include/libmaple/dma.h @@ -139,12 +139,12 @@ void dma_init(dma_dev *dev); */ typedef struct dma_tube_config { /** Source of data */ - __io void *tube_src; + __IO void *tube_src; /** Source transfer size */ dma_xfer_size tube_src_size; /** Destination of data */ - __io void *tube_dst; + __IO void *tube_dst; /** Destination transfer size */ dma_xfer_size tube_dst_size; @@ -283,7 +283,7 @@ extern void dma_set_num_transfers(dma_dev *dev, dma_tube tube, * @param tube Tube whose base memory address to set. * @param address Memory base address to use. */ -extern void dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *address); +extern void dma_set_mem_addr(dma_dev *dev, dma_tube tube, __IO void *address); /** * @brief Set the base peripheral address where data will be read from @@ -299,7 +299,7 @@ extern void dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *address); * @param tube Tube whose peripheral data register base address to set. * @param address Peripheral memory base address to use. */ -extern void dma_set_per_addr(dma_dev *dev, dma_tube tube, __io void *address); +extern void dma_set_per_addr(dma_dev *dev, dma_tube tube, __IO void *address); /* Interrupt handling */ diff --git a/STM32F1/system/libmaple/include/libmaple/exti.h b/STM32F1/system/libmaple/include/libmaple/exti.h index 69362d6..3e914be 100644 --- a/STM32F1/system/libmaple/include/libmaple/exti.h +++ b/STM32F1/system/libmaple/include/libmaple/exti.h @@ -48,12 +48,12 @@ extern "C"{ /** EXTI register map type */ typedef struct exti_reg_map { - __io uint32 IMR; /**< Interrupt mask register */ - __io uint32 EMR; /**< Event mask register */ - __io uint32 RTSR; /**< Rising trigger selection register */ - __io uint32 FTSR; /**< Falling trigger selection register */ - __io uint32 SWIER; /**< Software interrupt event register */ - __io uint32 PR; /**< Pending register */ + __IO uint32 IMR; /**< Interrupt mask register */ + __IO uint32 EMR; /**< Event mask register */ + __IO uint32 RTSR; /**< Rising trigger selection register */ + __IO uint32 FTSR; /**< Falling trigger selection register */ + __IO uint32 SWIER; /**< Software interrupt event register */ + __IO uint32 PR; /**< Pending register */ } exti_reg_map; /* diff --git a/STM32F1/system/libmaple/include/libmaple/fsmc.h b/STM32F1/system/libmaple/include/libmaple/fsmc.h index 6225fee..9dd8a72 100644 --- a/STM32F1/system/libmaple/include/libmaple/fsmc.h +++ b/STM32F1/system/libmaple/include/libmaple/fsmc.h @@ -53,42 +53,42 @@ extern "C"{ /** FSMC register map type */ typedef struct fsmc_reg_map { - __io uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ - __io uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ - __io uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ - __io uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ - __io uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ - __io uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ - __io uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ - __io uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ + __IO uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ + __IO uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ + __IO uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ + __IO uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ + __IO uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ + __IO uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ + __IO uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ + __IO uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ const uint8 RESERVED1[64]; /**< Reserved */ - __io uint32 PCR2; /**< PC Card/NAND Flash control register 2 */ - __io uint32 SR2; /**< FIFO status and interrupt register 2 */ - __io uint32 PMEM2; /**< Common memory space timing register 2 */ - __io uint32 PATT2; /**< Attribute memory space timing register 2 */ + __IO uint32 PCR2; /**< PC Card/NAND Flash control register 2 */ + __IO uint32 SR2; /**< FIFO status and interrupt register 2 */ + __IO uint32 PMEM2; /**< Common memory space timing register 2 */ + __IO uint32 PATT2; /**< Attribute memory space timing register 2 */ const uint8 RESERVED2[4]; /**< Reserved */ - __io uint32 ECCR2; /**< ECC result register 2 */ + __IO uint32 ECCR2; /**< ECC result register 2 */ const uint8 RESERVED3[2]; - __io uint32 PCR3; /**< PC Card/NAND Flash control register 3 */ - __io uint32 SR3; /**< FIFO status and interrupt register 3 */ - __io uint32 PMEM3; /**< Common memory space timing register 3 */ - __io uint32 PATT3; /**< Attribute memory space timing register 3 */ + __IO uint32 PCR3; /**< PC Card/NAND Flash control register 3 */ + __IO uint32 SR3; /**< FIFO status and interrupt register 3 */ + __IO uint32 PMEM3; /**< Common memory space timing register 3 */ + __IO uint32 PATT3; /**< Attribute memory space timing register 3 */ const uint32 RESERVED4; /**< Reserved */ - __io uint32 ECCR3; /**< ECC result register 3 */ + __IO uint32 ECCR3; /**< ECC result register 3 */ const uint8 RESERVED5[8]; /**< Reserved */ - __io uint32 PCR4; /**< PC Card/NAND Flash control register 4 */ - __io uint32 SR4; /**< FIFO status and interrupt register 4 */ - __io uint32 PMEM4; /**< Common memory space timing register 4 */ - __io uint32 PATT4; /**< Attribute memory space timing register 4 */ - __io uint32 PIO4; /**< I/O space timing register 4 */ + __IO uint32 PCR4; /**< PC Card/NAND Flash control register 4 */ + __IO uint32 SR4; /**< FIFO status and interrupt register 4 */ + __IO uint32 PMEM4; /**< Common memory space timing register 4 */ + __IO uint32 PATT4; /**< Attribute memory space timing register 4 */ + __IO uint32 PIO4; /**< I/O space timing register 4 */ const uint8 RESERVED6[80]; /**< Reserved */ - __io uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ + __IO uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ const uint32 RESERVED7; /**< Reserved */ - __io uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ + __IO uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ const uint32 RESERVED8; /**< Reserved */ - __io uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ + __IO uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ const uint32 RESERVED9; /**< Reserved */ - __io uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ + __IO uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ } __attribute__((packed)) fsmc_reg_map; #define __FSMCB 0xA0000000 @@ -98,10 +98,10 @@ typedef struct fsmc_reg_map { /** FSMC NOR/PSRAM register map type */ typedef struct fsmc_nor_psram_reg_map { - __io uint32 BCR; /**< Chip-select control register */ - __io uint32 BTR; /**< Chip-select timing register */ + __IO uint32 BCR; /**< Chip-select control register */ + __IO uint32 BTR; /**< Chip-select timing register */ const uint8 RESERVED[252]; /**< Reserved */ - __io uint32 BWTR; /**< Write timing register */ + __IO uint32 BWTR; /**< Write timing register */ } fsmc_nor_psram_reg_map; /** FSMC NOR/PSRAM base pointer 1 */ diff --git a/STM32F1/system/libmaple/include/libmaple/i2c.h b/STM32F1/system/libmaple/include/libmaple/i2c.h index 92ec29e..a44f6af 100644 --- a/STM32F1/system/libmaple/include/libmaple/i2c.h +++ b/STM32F1/system/libmaple/include/libmaple/i2c.h @@ -75,15 +75,15 @@ extern "C" { /** I2C register map type */ typedef struct i2c_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 OAR1; /**< Own address register 1 */ - __io uint32 OAR2; /**< Own address register 2 */ - __io uint32 DR; /**< Data register */ - __io uint32 SR1; /**< Status register 1 */ - __io uint32 SR2; /**< Status register 2 */ - __io uint32 CCR; /**< Clock control register */ - __io uint32 TRISE; /**< TRISE (rise time) register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 OAR1; /**< Own address register 1 */ + __IO uint32 OAR2; /**< Own address register 2 */ + __IO uint32 DR; /**< Data register */ + __IO uint32 SR1; /**< Status register 1 */ + __IO uint32 SR2; /**< Status register 2 */ + __IO uint32 CCR; /**< Clock control register */ + __IO uint32 TRISE; /**< TRISE (rise time) register */ } i2c_reg_map; /** diff --git a/STM32F1/system/libmaple/include/libmaple/iwdg.h b/STM32F1/system/libmaple/include/libmaple/iwdg.h index 3a16c55..f999439 100644 --- a/STM32F1/system/libmaple/include/libmaple/iwdg.h +++ b/STM32F1/system/libmaple/include/libmaple/iwdg.h @@ -53,10 +53,10 @@ extern "C"{ /** Independent watchdog register map type. */ typedef struct iwdg_reg_map { - __io uint32 KR; /**< Key register. */ - __io uint32 PR; /**< Prescaler register. */ - __io uint32 RLR; /**< Reload register. */ - __io uint32 SR; /**< Status register */ + __IO uint32 KR; /**< Key register. */ + __IO uint32 PR; /**< Prescaler register. */ + __IO uint32 RLR; /**< Reload register. */ + __IO uint32 SR; /**< Status register */ } iwdg_reg_map; /** Independent watchdog base pointer */ diff --git a/STM32F1/system/libmaple/include/libmaple/libmaple_types.h b/STM32F1/system/libmaple/include/libmaple/libmaple_types.h index 398b705..62bf436 100644 --- a/STM32F1/system/libmaple/include/libmaple/libmaple_types.h +++ b/STM32F1/system/libmaple/include/libmaple/libmaple_types.h @@ -52,7 +52,7 @@ typedef long long int64; typedef void (*voidFuncPtr)(void); typedef void (*voidArgumentFuncPtr)(void *); -#define __io volatile +#define __IO volatile #define __attr_flash __attribute__((section (".USER_FLASH"))) #define __packed __attribute__((__packed__)) #define __deprecated __attribute__((__deprecated__)) diff --git a/STM32F1/system/libmaple/include/libmaple/nvic.h b/STM32F1/system/libmaple/include/libmaple/nvic.h index 69d9a91..954fd12 100644 --- a/STM32F1/system/libmaple/include/libmaple/nvic.h +++ b/STM32F1/system/libmaple/include/libmaple/nvic.h @@ -55,31 +55,31 @@ extern "C"{ /** NVIC register map type. */ typedef struct nvic_reg_map { - __io uint32 ISER[8]; /**< Interrupt Set Enable Registers */ + __IO uint32 ISER[8]; /**< Interrupt Set Enable Registers */ /** Reserved */ uint32 RESERVED0[24]; - __io uint32 ICER[8]; /**< Interrupt Clear Enable Registers */ + __IO uint32 ICER[8]; /**< Interrupt Clear Enable Registers */ /** Reserved */ uint32 RESERVED1[24]; - __io uint32 ISPR[8]; /**< Interrupt Set Pending Registers */ + __IO uint32 ISPR[8]; /**< Interrupt Set Pending Registers */ /** Reserved */ uint32 RESERVED2[24]; - __io uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */ + __IO uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */ /** Reserved */ uint32 RESERVED3[24]; - __io uint32 IABR[8]; /**< Interrupt Active bit Registers */ + __IO uint32 IABR[8]; /**< Interrupt Active bit Registers */ /** Reserved */ uint32 RESERVED4[56]; - __io uint8 IP[240]; /**< Interrupt Priority Registers */ + __IO uint8 IP[240]; /**< Interrupt Priority Registers */ /** Reserved */ uint32 RESERVED5[644]; - __io uint32 STIR; /**< Software Trigger Interrupt Registers */ + __IO uint32 STIR; /**< Software Trigger Interrupt Registers */ } nvic_reg_map; /** NVIC register map base pointer. */ diff --git a/STM32F1/system/libmaple/include/libmaple/pwr.h b/STM32F1/system/libmaple/include/libmaple/pwr.h index f711c7c..fada6df 100644 --- a/STM32F1/system/libmaple/include/libmaple/pwr.h +++ b/STM32F1/system/libmaple/include/libmaple/pwr.h @@ -43,8 +43,8 @@ extern "C" { /** Power interface register map. */ typedef struct pwr_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 CSR; /**< Control and status register */ + __IO uint32 CR; /**< Control register */ + __IO uint32 CSR; /**< Control and status register */ } pwr_reg_map; /** Power peripheral register map base pointer. */ diff --git a/STM32F1/system/libmaple/include/libmaple/ring_buffer.h b/STM32F1/system/libmaple/include/libmaple/ring_buffer.h index eb38634..854d589 100644 --- a/STM32F1/system/libmaple/include/libmaple/ring_buffer.h +++ b/STM32F1/system/libmaple/include/libmaple/ring_buffer.h @@ -52,9 +52,9 @@ extern "C"{ * One byte is left free to distinguish empty from full. */ typedef struct ring_buffer { volatile uint8 *buf; /**< Buffer items are stored into */ - uint16 head; /**< Index of the next item to remove */ - uint16 tail; /**< Index where the next item will get inserted */ - uint16 size; /**< Buffer capacity minus one */ + volatile uint16 head; /**< Index of the next item to remove */ + volatile uint16 tail; /**< Index where the next item will get inserted */ + volatile uint16 size; /**< Buffer capacity minus one */ } ring_buffer; /** @@ -81,7 +81,7 @@ static inline void rb_init(ring_buffer *rb, uint16 size, uint8 *buf) { * @param rb Buffer whose elements to count. */ static inline uint16 rb_full_count(ring_buffer *rb) { - __io ring_buffer *arb = rb; + __IO ring_buffer *arb = rb; int32 size = arb->tail - arb->head; if (arb->tail < arb->head) { size += arb->size + 1; diff --git a/STM32F1/system/libmaple/include/libmaple/scb.h b/STM32F1/system/libmaple/include/libmaple/scb.h index c42a0f2..d58434c 100644 --- a/STM32F1/system/libmaple/include/libmaple/scb.h +++ b/STM32F1/system/libmaple/include/libmaple/scb.h @@ -49,37 +49,37 @@ extern "C" { /** System control block register map type */ typedef struct scb_reg_map { - __io uint32 CPUID; /**< CPU ID Base Register */ - __io uint32 ICSR; /**< Interrupt Control State Register */ - __io uint32 VTOR; /**< Vector Table Offset Register */ - __io uint32 AIRCR; /**< Application Interrupt / Reset Control Register */ - __io uint32 SCR; /**< System Control Register */ - __io uint32 CCR; /**< Configuration and Control Register */ - __io uint8 SHP[12]; /**< System Handler Priority Registers + __IO uint32 CPUID; /**< CPU ID Base Register */ + __IO uint32 ICSR; /**< Interrupt Control State Register */ + __IO uint32 VTOR; /**< Vector Table Offset Register */ + __IO uint32 AIRCR; /**< Application Interrupt / Reset Control Register */ + __IO uint32 SCR; /**< System Control Register */ + __IO uint32 CCR; /**< Configuration and Control Register */ + __IO uint8 SHP[12]; /**< System Handler Priority Registers (4-7, 8-11, 12-15) */ - __io uint32 SHCSR; /**< System Handler Control and State Register */ - __io uint32 CFSR; /**< Configurable Fault Status Register */ - __io uint32 HFSR; /**< Hard Fault Status Register */ + __IO uint32 SHCSR; /**< System Handler Control and State Register */ + __IO uint32 CFSR; /**< Configurable Fault Status Register */ + __IO uint32 HFSR; /**< Hard Fault Status Register */ /* DFSR is not documented by ST in PM0056 (as of Revision 4), but * there's a 4 byte hole in the SCB register map docs right where * it belongs. Since it's specified as "always implemented" in * the ARM v7-M ARM, I'm assuming its absence is a bug in the ST * doc, but I haven't proven it. [mbolivar] */ - __io uint32 DFSR; /**< Debug Fault Status Register */ - __io uint32 MMFAR; /**< Mem Manage Address Register */ - __io uint32 BFAR; /**< Bus Fault Address Register */ + __IO uint32 DFSR; /**< Debug Fault Status Register */ + __IO uint32 MMFAR; /**< Mem Manage Address Register */ + __IO uint32 BFAR; /**< Bus Fault Address Register */ #if 0 /* The following registers are implementation-defined according to * ARM v7-M, and I can't find evidence of their existence in ST's * docs. I'm removing them. Feel free to yell at me if they do * exist. [mbolivar] */ - __io uint32 AFSR; /**< Auxiliary Fault Status Register */ - __io uint32 PFR[2]; /**< Processor Feature Register */ - __io uint32 DFR; /**< Debug Feature Register */ - __io uint32 AFR; /**< Auxiliary Feature Register */ - __io uint32 MMFR[4]; /**< Memory Model Feature Register */ - __io uint32 ISAR[5]; /**< ISA Feature Register */ + __IO uint32 AFSR; /**< Auxiliary Fault Status Register */ + __IO uint32 PFR[2]; /**< Processor Feature Register */ + __IO uint32 DFR; /**< Debug Feature Register */ + __IO uint32 AFR; /**< Auxiliary Feature Register */ + __IO uint32 MMFR[4]; /**< Memory Model Feature Register */ + __IO uint32 ISAR[5]; /**< ISA Feature Register */ #endif } scb_reg_map; @@ -122,7 +122,7 @@ typedef struct scb_reg_map { #define SCB_AIRCR_VECTKEYSTAT (0x5FA << 16) #define SCB_AIRCR_VECTKEY (0x5FA << 16) #define SCB_AIRCR_ENDIANNESS (1U << 15) -#define SCB_AIRCR_PRIGROUP (0x3 << 8) +#define SCB_AIRCR_PRIGROUP (0x7 << 8) #define SCB_AIRCR_SYSRESETREQ (1U << 2) #define SCB_AIRCR_VECTCLRACTIVE (1U << 1) #define SCB_AIRCR_VECTRESET (1U << 0) diff --git a/STM32F1/system/libmaple/include/libmaple/sdio.h b/STM32F1/system/libmaple/include/libmaple/sdio.h new file mode 100644 index 0000000..11ec986 --- /dev/null +++ b/STM32F1/system/libmaple/include/libmaple/sdio.h @@ -0,0 +1,270 @@ +/****************************************************************************** + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file sdio.h + * @brief Secure digital input/output interface. + */ + +#ifndef _SDIO_H_ +#define _SDIO_H_ + +#include +#include +#include + + +/* +#include +#include + +//#include +#include +//#include + */ + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + +/* + * DMA controller and channel used in STM32F103 + */ + +#define SDIO_DMA_DEV DMA2 +#define SDIO_DMA_CHANNEL DMA_CH4 +/* +#ifdef __cplusplus +extern "C" { +#endif +*/ + +/* + * Register maps and devices + */ + +// SDIO register map type +typedef struct sdio_reg_map { + __IO uint32 POWER; // 0x00 + __IO uint32 CLKCR; // 0x04 + __IO uint32 ARG; // 0x08 + __IO uint32 CMD; // 0x0C + __IO uint32 RESPCMD; // 0x10 (0x3F) + __IO const uint32 RESP[4]; // 0x14 - contain the card status, which is part of the received response. + __IO uint32 DTIMER; // 0x24 - contains the data timeout period, in card bus clock periods. + __IO uint32 DLEN; // 0x28 (0x01FF FFFF) - contains the number of data bytes to be transferred + __IO uint32 DCTRL; // 0x2C + __IO uint32 DCOUNT; // 0x30 (0x01FF FFFF) + __IO uint32 STA; // 0x34 + __IO uint32 ICR; // 0x38 + __IO uint32 MASK; // 0x3C + const uint32 RESERVED1[2]; + __IO uint32 FIFOCNT; // 0x48 (0x01FF FFFF) + const uint32 RESERVED2[13]; + __IO uint32 FIFO; // 0x80 +} sdio_reg_map; +#define sdio_dev sdio_reg_map + +/** SDIO register map base pointer */ +#define SDIO_BASE ((struct sdio_reg_map*)0x40018000) + +extern sdio_dev * SDIO; + +/* + * Register bit definitions + */ + +/* NOR/PSRAM chip-select control registers */ + +// SDIO_POWER register bits +// At least seven HCLK clock periods are needed between two write accesses to this register. +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +#define SDIO_POWER_PWRCTRL_OFF 0x00 +#define SDIO_POWER_PWRCTRL_ON 0x03 + +// SDIO_CLKCR register bits +// Controls the SDIO_CK output clock. +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. SDIO_CK can also be stopped during the read wait interval +// for SD I/O cards: in this case the SDIO_CLKCR register does not control SDIO_CK. +#define SDIO_CLKCR_HWFC_EN (1<<14) // HW Flow Control enable - DON'T USE in F4!!! (see errata sheet 2.12.1) + // Overrun errors (Rx mode) and FIFO underrun (Tx mode) + // should be managed by the application software. +#define SDIO_CLKCR_NEGEDGE (1<<13) // SDIO_CK de-phasing selection bit - DON'T USE!!! (see errata sheet 2.12.4) +#define SDIO_CLKCR_WIDBUS (3<<11) // Data bus width +#define SDIO_CLKCR_WIDBUS_1BIT (0<<11) // 1 bit (SDIO_D0 used) +#define SDIO_CLKCR_WIDBUS_4BIT (1<<11) // 4-bit (SDIO_D[3:0] used) +#define SDIO_CLKCR_BYPASS (1<<10) // Clock divider bypass enable bit - SDIO_CK = SDIOCLK, CLKDIV not relevant. +#define SDIO_CLKCR_PWRSAV (1<<9) // 0: SDIO_CK clock is always enabled, 1: SDIO_CK is only enabled when the bus is active +#define SDIO_CLKCR_CLKEN (1<<8) // Clock enable +#define SDIO_CLKCR_CLKDIV (0xFF) // SDIO_CK = SDIOCLK / [CLKDIV + 2] +#define SDIOCLK PCLK2 // SDIO master clock frequency + +// SDIO_CMD register bits +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +// MultiMediaCards can send two kinds of response: short responses, 48 bits long, or long +// responses,136 bits long. SD card and SD I/O card can send only short responses, the +// argument can vary according to the type of response: the software will distinguish the type +// of response according to the sent command. CE-ATA devices send only short responses. +#define SDIO_CMD_ATACMD (1<<14) +#define SDIO_CMD_NIEN (1<<13) +#define SDIO_CMD_ENCMDCOMPL (1<<12) +#define SDIO_CMD_SDIOSUSPEND (1<<11) +#define SDIO_CMD_CPSMEN (1<<10) +#define SDIO_CMD_WAITPEND (1<<9) +#define SDIO_CMD_WAITINT (1<<8) +#define SDIO_CMD_WAITRESP (3<<6) +#define SDIO_CMD_WAIT_NO_RESP (0<<6) +#define SDIO_CMD_WAIT_SHORT_RESP (1<<6) +#define SDIO_CMD_WAIT_LONG_RESP (3<<6) +#define SDIO_CMD_CMDINDEX (0x3F) + +// SDIO_DLEN register bits +// For a block data transfer, the value in the data length register must be a multiple of the block +// size (see SDIO_DCTRL). A data transfer must be written to the data timer register and the +// data length register before being written to the data control register. +// For an SDIO multibyte transfer the value in the data length register must be between 1 and 512. +#define SDIO_DLEN_DATALENGTH (0x01FFFFFF) + +// SDIO_DCTRL register bits +// Controls the data path state machine (DPSM). +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +#define SDIO_DCTRL_SDIOEN (1<<11) // the DPSM performs an SD I/O-card-specific operation. +#define SDIO_DCTRL_RWMODE (1<<10) // 0: Read Wait control stopping SDIO_D2, 1:Read Wait control using SDIO_CK +#define SDIO_DCTRL_RWSTOP (1<<9) // 0: Read wait in progress if RWSTART bit is set, 1: Enable for read wait stop if RWSTART bit is set +#define SDIO_DCTRL_RWSTART (1<<8) // read wait operation starts +#define SDIO_DCTRL_DBLOCKSIZE (0xF<<4) // Define the data block length when the block data transfer mode is selected: 2^N bytes +#define SDIO_BLOCKSIZE_64 (6<<4) +#define SDIO_BLOCKSIZE_512 (9<<4) +#define SDIO_DCTRL_DMAEN (1<<3) // DMA enable +#define SDIO_DCTRL_DTMODE (1<<2) // Data transfer mode selection: 0: Block data transfer, 1: Stream or SDIO multi-byte data transfer +#define SDIO_DCTRL_DTDIR (1<<1) // Data transfer direction selection: 0: From controller to card, 1: From card to controller. +#define SDIO_DIR_TX (0<<1) +#define SDIO_DIR_RX (1<<1) +#define SDIO_DCTRL_DTEN (1<<0) // Start data transfer. Depending on the direction bit, DTDIR, + // the DPSM moves to the Wait_S, Wait_R state or Readwait if RW Start is set immediately at + // the beginning of the transfer. It is not necessary to clear the enable bit after the end of a data + // transfer but the SDIO_DCTRL must be updated to enable a new data transfer +// The meaning of the DTMODE bit changes according to the value of the SDIOEN bit: +// When DTEN=0 and DTMODE=1, the MultiMediaCard stream mode is enabled. +// When DTEN=1 and DTMODE=1, the peripheral enables an SDIO multi-byte transfer. + +// SDIO_STA register bits +#define SDIO_STA_CEATAEND (1<<23) // CE-ATA command completion signal received for CMD61 +#define SDIO_STA_SDIOIT (1<<22) // SDIO interrupt received +#define SDIO_STA_RXDAVL (1<<21) // Data available in receive FIFO +#define SDIO_STA_TXDAVL (1<<20) // Data available in transmit FIFO +#define SDIO_STA_RXFIFOE (1<<19) // Receive FIFO empty +#define SDIO_STA_TXFIFOE (1<<18) // Transmit FIFO empty (2 words) +#define SDIO_STA_RXFIFOF (1<<17) // Receive FIFO full (2 words before the FIFO is full.) +#define SDIO_STA_TXFIFOF (1<<16) // Transmit FIFO full +#define SDIO_STA_RXFIFOHF (1<<15) // Receive FIFO half full: there are at least 8 words in the FIFO +#define SDIO_STA_TXFIFOHE (1<<14) // Transmit FIFO half empty: at least 8 words can be written into the FIFO +#define SDIO_STA_RXACT (1<<13) // Data receive in progress +#define SDIO_STA_TXACT (1<<12) // Data transmit in progress +#define SDIO_STA_CMDACT (1<<11) // Command transfer in progress +#define SDIO_STA_DBCKEND (1<<10) // Data block sent/received (CRC check passed) +#define SDIO_STA_STBITERR (1<<9) // Start bit not detected on all data signals in wide bus mode +#define SDIO_STA_DATAEND (1<<8) // Data end (data counter SDIOCOUNT is zero) +#define SDIO_STA_CMDSENT (1<<7) // Command sent (no response required) +#define SDIO_STA_CMDREND (1<<6) // Command response received (CRC check passed) +#define SDIO_STA_RXOVERR (1<<5) // Received FIFO overrun error +#define SDIO_STA_TXUNDERR (1<<4) // Transmit FIFO underrun error +#define SDIO_STA_DTIMEOUT (1<<3) // Data timeout +#define SDIO_STA_CTIMEOUT (1<<2) // Command response timeout. The Command TimeOut period has a fixed value of 64 SDIO_CK clock periods. +#define SDIO_STA_DCRCFAIL (1<<1) // Data block sent/received (CRC check failed) +#define SDIO_STA_CCRCFAIL (1<<0) // Command response received (CRC check failed) + +#define SDIO_STA_CMD_ERROR_FLAGS (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL) +#define SDIO_STA_TRX_ERROR_FLAGS (SDIO_STA_STBITERR | SDIO_STA_RXOVERR | SDIO_STA_TXUNDERR | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL) +#define SDIO_STA_TRX_ACT_FLAGS (SDIO_STA_RXACT|SDIO_STA_TXACT) + +// SDIO_ICR register bits (WO - write only) +#define SDIO_ICR_CEATAENDC (1<<23) // clear CEATAEND flag +#define SDIO_ICR_SDIOITC (1<<22) // clear SDIOIT flag +#define SDIO_ICR_DBCKENDC (1<<10) // clear DBCKENDC flag +#define SDIO_ICR_STBITERRC (1<<9) // clear STBITERRC flag +#define SDIO_ICR_DATAENDC (1<<8) // clear DATAENDC flag +#define SDIO_ICR_CMDSENTC (1<<7) // clear CMDSENTC flag +#define SDIO_ICR_CMDRENDC (1<<6) // clear CMDREND flag +#define SDIO_ICR_RXOVERRC (1<<5) // clear RXOVERR flag +#define SDIO_ICR_TXUNDERRC (1<<4) // clear TXUNDERR flag +#define SDIO_ICR_DTIMEOUTC (1<<3) // clear DTIMEOUT flag +#define SDIO_ICR_CTIMEOUTC (1<<2) // clear CTIMEOUT flag +#define SDIO_ICR_DCRCFAILC (1<<1) // clear DCRCFAIL flag +#define SDIO_ICR_CCRCFAILC (1<<0) // clear CCRCFAIL flag + +#define SDIO_ICR_CMD_FLAGS (SDIO_ICR_CEATAENDC | SDIO_ICR_SDIOITC | SDIO_ICR_CMDSENTC | SDIO_ICR_CMDRENDC | SDIO_ICR_CTIMEOUTC | SDIO_ICR_CCRCFAILC) +#define SDIO_ICR_DATA_FLAGS (SDIO_ICR_DBCKENDC | SDIO_ICR_STBITERRC | SDIO_ICR_DATAENDC | SDIO_ICR_RXOVERRC | SDIO_ICR_TXUNDERRC | SDIO_ICR_DTIMEOUTC | SDIO_ICR_DCRCFAILC) + +// SDIO_MASK register bits +// Determines which status flags generate an interrupt request by setting the corresponding bit to 1b. +#define SDIO_MASK_CEATAENDIE (1<<23) // enable CEATAEND interrupt +#define SDIO_MASK_SDIOITIE (1<<22) // enable SDIOIT interrupt +#define SDIO_MASK_RXDAVLIE (1<<21) // enable RXDAVL interrupt +#define SDIO_MASK_TXDAVLIE (1<<20) // enable TXDAVL interrupt +#define SDIO_MASK_RXFIFOEIE (1<<19) // enable RXFIFOE interrupt +#define SDIO_MASK_TXFIFOEIE (1<<18) // enable TXFIFOE interrupt +#define SDIO_MASK_RXFIFOFIE (1<<17) // enable RXFIFOF interrupt +#define SDIO_MASK_TXFIFOFIE (1<<16) // enable TXFIFOF interrupt +#define SDIO_MASK_RXFIFOHFIE (1<<15) // enable RXFIFOHF interrupt +#define SDIO_MASK_TXFIFOHEIE (1<<14) // enable TXFIFOHE interrupt +#define SDIO_MASK_RXACTIE (1<<13) // enable RXACT interrupt +#define SDIO_MASK_TXACTIE (1<<12) // enable TXACT interrupt +#define SDIO_MASK_CMDACTIE (1<<11) // enable CMDACT interrupt +#define SDIO_MASK_DBCKENDIE (1<<10) // enable DBCKENDC interrupt +#define SDIO_MASK_STBITERRIE (1<<9) // enable STBITERR interrupt +#define SDIO_MASK_DATAENDIE (1<<8) // enable DATAENDC interrupt +#define SDIO_MASK_CMDSENTIE (1<<7) // enable CMDSENTC interrupt +#define SDIO_MASK_CMDRENDIE (1<<6) // enable CMDREND interrupt +#define SDIO_MASK_RXOVERRIE (1<<5) // enable RXOVERR interrupt +#define SDIO_MASK_TXUNDERRIE (1<<4) // enable TXUNDERR interrupt +#define SDIO_MASK_DTIMEOUTIE (1<<3) // enable DTIMEOUT interrupt +#define SDIO_MASK_CTIMEOUTIE (1<<2) // enable CTIMEOUT interrupt +#define SDIO_MASK_DCRCFAILIE (1<<1) // enable DCRCFAIL interrupt +#define SDIO_MASK_CCRCFAILIE (1<<0) // enable CCRCFAIL interrupt + + +void sdio_enable(void); +void sdio_disable(void); +void sdio_begin(void); +uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg); +void sdio_set_clock(uint32_t clk); +void sdio_set_dbus_width(uint16_t bus_w); +void sdio_set_dblock_size(uint8_t dbsize); +//void sdio_trx_enable(uint8_t dir); +inline void sdio_trx_enable(void) +{ + SDIO->DCTRL |= SDIO_DCTRL_DTEN; // enable data transfer +} + +inline uint32_t sdio_cmd_xfer_ongoing(void) { return (SDIO->STA&SDIO_STA_CMDACT); } +inline uint32_t sdio_cmd_complete(void) { return (SDIO->STA&SDIO_STA_CMDSENT); } + +inline void sdio_setup_transfer(uint32_t dtimer, uint32_t dlen, uint16_t flags) +{ + SDIO->ICR = SDIO_ICR_DATA_FLAGS; // clear data access relevant flags + SDIO->DTIMER = dtimer; + SDIO->DLEN = dlen; + SDIO->DCTRL = flags;// | SDIO_DCTRL_DTEN; // enable data transfer +} + +/* +#ifdef __cplusplus +} // extern "C" +#endif +*/ + +#endif /* (STM32_HIGH_DENSITY) || (STM32_XL_DENSITY) */ + +#endif diff --git a/STM32F1/system/libmaple/include/libmaple/spi.h b/STM32F1/system/libmaple/include/libmaple/spi.h index 0da4129..5d295bb 100644 --- a/STM32F1/system/libmaple/include/libmaple/spi.h +++ b/STM32F1/system/libmaple/include/libmaple/spi.h @@ -54,15 +54,15 @@ extern "C" { /** SPI register map type. */ typedef struct spi_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SR; /**< Status register */ - __io uint32 DR; /**< Data register */ - __io uint32 CRCPR; /**< CRC polynomial register */ - __io uint32 RXCRCR; /**< RX CRC register */ - __io uint32 TXCRCR; /**< TX CRC register */ - __io uint32 I2SCFGR; /**< I2S configuration register */ - __io uint32 I2SPR; /**< I2S prescaler register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SR; /**< Status register */ + __IO uint32 DR; /**< Data register */ + __IO uint32 CRCPR; /**< CRC polynomial register */ + __IO uint32 RXCRCR; /**< RX CRC register */ + __IO uint32 TXCRCR; /**< TX CRC register */ + __IO uint32 I2SCFGR; /**< I2S configuration register */ + __IO uint32 I2SPR; /**< I2S prescaler register */ } spi_reg_map; /* diff --git a/STM32F1/system/libmaple/include/libmaple/syscfg.h b/STM32F1/system/libmaple/include/libmaple/syscfg.h index 6b375d3..e39d0b7 100644 --- a/STM32F1/system/libmaple/include/libmaple/syscfg.h +++ b/STM32F1/system/libmaple/include/libmaple/syscfg.h @@ -48,12 +48,12 @@ extern "C" { * @brief SYSCFG register map type. */ typedef struct syscfg_reg_map { - __io uint32 MEMRMP; /**< Memory remap register */ - __io uint32 PMC; /**< Peripheral mode configuration */ - __io uint32 EXTICR[4]; /**< External interrupt configuration registers */ + __IO uint32 MEMRMP; /**< Memory remap register */ + __IO uint32 PMC; /**< Peripheral mode configuration */ + __IO uint32 EXTICR[4]; /**< External interrupt configuration registers */ const uint32 RESERVED1; const uint32 RESERVED2; - __io uint32 CMPCR; /**< Compensation cell control register */ + __IO uint32 CMPCR; /**< Compensation cell control register */ } syscfg_reg_map; /** SYSCFG register map base pointer */ diff --git a/STM32F1/system/libmaple/include/libmaple/systick.h b/STM32F1/system/libmaple/include/libmaple/systick.h index 551f800..3f6bd5f 100644 --- a/STM32F1/system/libmaple/include/libmaple/systick.h +++ b/STM32F1/system/libmaple/include/libmaple/systick.h @@ -41,10 +41,10 @@ extern "C"{ /** SysTick register map type */ typedef struct systick_reg_map { - __io uint32 CSR; /**< Control and status register */ - __io uint32 RVR; /**< Reload value register */ - __io uint32 CNT; /**< Current value register ("count") */ - __io uint32 CVR; /**< Calibration value register */ + __IO uint32 CSR; /**< Control and status register */ + __IO uint32 RVR; /**< Reload value register */ + __IO uint32 CNT; /**< Current value register ("count") */ + __IO uint32 CVR; /**< Calibration value register */ } systick_reg_map; /** SysTick register map base pointer */ @@ -108,6 +108,12 @@ static inline uint32 systick_check_underflow(void) { return SYSTICK_BASE->CSR & SYSTICK_CSR_COUNTFLAG; } +/** + * @brief prototype for systick_attach_callback + * + */ +extern void systick_attach_callback(void (*callback)(void)); + #ifdef __cplusplus } // extern "C" #endif diff --git a/STM32F1/system/libmaple/include/libmaple/timer.h b/STM32F1/system/libmaple/include/libmaple/timer.h index 59b3403..87b83e5 100644 --- a/STM32F1/system/libmaple/include/libmaple/timer.h +++ b/STM32F1/system/libmaple/include/libmaple/timer.h @@ -50,26 +50,26 @@ extern "C"{ /** Advanced control timer register map type */ typedef struct timer_adv_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ - __io uint32 RCR; /**< Repetition counter register */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ - __io uint32 BDTR; /**< Break and dead-time register */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SMCR; /**< Slave mode control register */ + __IO uint32 DIER; /**< DMA/interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ + __IO uint32 CCMR1; /**< Capture/compare mode register 1 */ + __IO uint32 CCMR2; /**< Capture/compare mode register 2 */ + __IO uint32 CCER; /**< Capture/compare enable register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ + __IO uint32 RCR; /**< Repetition counter register */ + __IO uint32 CCR1; /**< Capture/compare register 1 */ + __IO uint32 CCR2; /**< Capture/compare register 2 */ + __IO uint32 CCR3; /**< Capture/compare register 3 */ + __IO uint32 CCR4; /**< Capture/compare register 4 */ + __IO uint32 BDTR; /**< Break and dead-time register */ + __IO uint32 DCR; /**< DMA control register */ + __IO uint32 DMAR; /**< DMA address for full transfer */ } timer_adv_reg_map; /* General purpose timer register map type: intentionally omitted. @@ -79,18 +79,18 @@ typedef struct timer_adv_reg_map { /** Basic timer register map type */ typedef struct timer_bas_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ const uint32 RESERVED1; /**< Reserved */ - __io uint32 DIER; /**< DMA/interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ + __IO uint32 DIER; /**< DMA/interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ const uint32 RESERVED2; /**< Reserved */ const uint32 RESERVED3; /**< Reserved */ const uint32 RESERVED4; /**< Reserved */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ } timer_bas_reg_map; /* @@ -372,7 +372,6 @@ extern timer_dev timer14; /* Capture/compare mode registers, common values */ -#define TIMER_CCMR_CCS_OUTPUT 0x0 #define TIMER_CCMR_CCS_INPUT_TI1 0x1 #define TIMER_CCMR_CCS_INPUT_TI2 0x2 #define TIMER_CCMR_CCS_INPUT_TRC 0x3 @@ -387,27 +386,27 @@ extern timer_dev timer14; #define TIMER_CCMR1_OC1FE_BIT 2 #define TIMER_CCMR1_OC2CE (1U << TIMER_CCMR1_OC2CE_BIT) -#define TIMER_CCMR1_OC2M (0x3 << 12) +#define TIMER_CCMR1_OC2M (0x7 << 12) #define TIMER_CCMR1_IC2F (0xF << 12) #define TIMER_CCMR1_OC2PE (1U << TIMER_CCMR1_OC2PE_BIT) #define TIMER_CCMR1_OC2FE (1U << TIMER_CCMR1_OC2FE_BIT) #define TIMER_CCMR1_IC2PSC (0x3 << 10) #define TIMER_CCMR1_CC2S (0x3 << 8) -#define TIMER_CCMR1_CC2S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) -#define TIMER_CCMR1_CC2S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) -#define TIMER_CCMR1_CC2S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) -#define TIMER_CCMR1_CC2S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) +#define TIMER_CCMR1_CC2S_OUTPUT (0x0 << 8) +#define TIMER_CCMR1_CC2S_INPUT_TI2 (0x1 << 8) +#define TIMER_CCMR1_CC2S_INPUT_TI1 (0x2 << 8) +#define TIMER_CCMR1_CC2S_INPUT_TRC (0x3 << 8) #define TIMER_CCMR1_OC1CE (1U << TIMER_CCMR1_OC1CE_BIT) -#define TIMER_CCMR1_OC1M (0x3 << 4) +#define TIMER_CCMR1_OC1M (0x7 << 4) #define TIMER_CCMR1_IC1F (0xF << 4) #define TIMER_CCMR1_OC1PE (1U << TIMER_CCMR1_OC1PE_BIT) #define TIMER_CCMR1_OC1FE (1U << TIMER_CCMR1_OC1FE_BIT) #define TIMER_CCMR1_IC1PSC (0x3 << 2) #define TIMER_CCMR1_CC1S 0x3 -#define TIMER_CCMR1_CC1S_OUTPUT TIMER_CCMR_CCS_OUTPUT -#define TIMER_CCMR1_CC1S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 -#define TIMER_CCMR1_CC1S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 -#define TIMER_CCMR1_CC1S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC +#define TIMER_CCMR1_CC1S_OUTPUT 0x0 +#define TIMER_CCMR1_CC1S_INPUT_TI1 0x1 +#define TIMER_CCMR1_CC1S_INPUT_TI2 0x2 +#define TIMER_CCMR1_CC1S_INPUT_TRC 0x3 /* Capture/compare mode register 2 (CCMR2) */ @@ -419,27 +418,27 @@ extern timer_dev timer14; #define TIMER_CCMR2_OC3FE_BIT 2 #define TIMER_CCMR2_OC4CE (1U << TIMER_CCMR2_OC4CE_BIT) -#define TIMER_CCMR2_OC4M (0x3 << 12) +#define TIMER_CCMR2_OC4M (0x7 << 12) #define TIMER_CCMR2_IC4F (0xF << 12) #define TIMER_CCMR2_OC4PE (1U << TIMER_CCMR2_OC4PE_BIT) #define TIMER_CCMR2_OC4FE (1U << TIMER_CCMR2_OC4FE_BIT) #define TIMER_CCMR2_IC4PSC (0x3 << 10) #define TIMER_CCMR2_CC4S (0x3 << 8) -#define TIMER_CCMR2_CC4S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) -#define TIMER_CCMR2_CC4S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) -#define TIMER_CCMR2_CC4S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) -#define TIMER_CCMR2_CC4S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) +#define TIMER_CCMR2_CC4S_OUTPUT (0x0 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TI4 (0x1 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TI3 (0x2 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TRC (0x3 << 8) #define TIMER_CCMR2_OC3CE (1U << TIMER_CCMR2_OC3CE_BIT) -#define TIMER_CCMR2_OC3M (0x3 << 4) +#define TIMER_CCMR2_OC3M (0x7 << 4) #define TIMER_CCMR2_IC3F (0xF << 4) #define TIMER_CCMR2_OC3PE (1U << TIMER_CCMR2_OC3PE_BIT) #define TIMER_CCMR2_OC3FE (1U << TIMER_CCMR2_OC3FE_BIT) #define TIMER_CCMR2_IC3PSC (0x3 << 2) #define TIMER_CCMR2_CC3S 0x3 -#define TIMER_CCMR2_CC3S_OUTPUT TIMER_CCMR_CCS_OUTPUT -#define TIMER_CCMR2_CC3S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 -#define TIMER_CCMR2_CC3S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 -#define TIMER_CCMR2_CC3S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC +#define TIMER_CCMR2_CC3S_OUTPUT 0x0 +#define TIMER_CCMR2_CC3S_INPUT_TI3 0x1 +#define TIMER_CCMR2_CC3S_INPUT_TI4 0x2 +#define TIMER_CCMR2_CC3S_INPUT_TRC 0x3 /* Capture/compare enable register (CCER) */ @@ -564,13 +563,15 @@ typedef enum timer_mode { * values, the corresponding interrupt is fired. */ TIMER_OUTPUT_COMPARE, - /* TIMER_INPUT_CAPTURE, TODO: In this mode, the timer can measure the + + /* TIMER_INPUT_CAPTURE, UNDER DEVELOPMENT: In this mode, the timer can measure the * pulse lengths of input signals */ /* TIMER_ONE_PULSE, TODO: In this mode, the timer can generate a single * pulse on a GPIO pin for a specified amount of * time. */ TIMER_ENCODER, //CARLOS Change + TIMER_INPUT_CAPTURE,// code from @cesco } timer_mode; /** Timer channel numbers */ @@ -663,6 +664,19 @@ static inline void timer_resume(timer_dev *dev) { *bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 1; } +/** + * @brief Get the status register. + * @param dev Timer device + * @return Status register value (16bits). + */ +static inline uint16 timer_get_status(timer_dev *dev) { + return (dev->regs).gen->SR; +} + +static inline void timer_reset_status_bit(timer_dev *dev, uint8 bit) { + *bb_perip(&(dev->regs).gen->SR, bit) = 0; +} + /** * @brief Returns the timer's counter value. * @@ -738,7 +752,7 @@ static inline void timer_set_reload(timer_dev *dev, uint16 arr) { * @param channel Channel whose compare value to get. */ static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) { - __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); + __IO uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); return *ccr; } @@ -751,7 +765,7 @@ static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) { static inline void timer_set_compare(timer_dev *dev, uint8 channel, uint16 value) { - __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); + __IO uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); *ccr = value; } @@ -785,6 +799,22 @@ static inline void timer_dma_disable_trg_req(timer_dev *dev) { *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 0; } +/** + * @brief Enable a timer's update DMA request + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + */ +static inline void timer_dma_enable_upd_req(timer_dev *dev) { + *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_UDE_BIT) = 1; +} + +/** + * @brief Disable a timer's update DMA request + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + */ +static inline void timer_dma_disable_upd_req(timer_dev *dev) { + *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_UDE_BIT) = 0; +} + /** * @brief Enable a timer channel's DMA request. * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL @@ -812,6 +842,9 @@ static inline void timer_dma_disable_req(timer_dev *dev, uint8 channel) { * @see timer_channel */ static inline void timer_enable_irq(timer_dev *dev, uint8 interrupt) { + // clear interrupt flag, use different masks for reserved bits + (dev->regs).adv->SR = (~BIT(interrupt)) & ( (dev->type==TIMER_ADVANCED) ? 0x1EFF : + ( (dev->type==TIMER_GENERAL) ? 0x1E5F : 0x0001) ); *bb_perip(&(dev->regs).adv->DIER, interrupt) = 1; } @@ -1048,82 +1081,27 @@ static inline void timer_oc_set_mode(timer_dev *dev, timer_oc_mode mode, uint8 flags) { /* channel == 1,2 -> CCMR1; channel == 3,4 -> CCMR2 */ - __io uint32 *ccmr = &(dev->regs).gen->CCMR1 + (((channel - 1) >> 1) & 1); + __IO uint32 *ccmr = &(dev->regs).gen->CCMR1 + (((channel - 1) >> 1) & 1); /* channel == 1,3 -> shift = 0, channel == 2,4 -> shift = 8 */ uint8 shift = 8 * (1 - (channel & 1)); uint32 tmp = *ccmr; tmp &= ~(0xFF << shift); - tmp |= (mode | flags | TIMER_CCMR_CCS_OUTPUT) << shift; + tmp |= (mode | flags) << shift; *ccmr = tmp; } -/* - * Old, erroneous bit definitions from previous releases, kept for - * backwards compatibility: +/** + * Timer output compare modes. */ +typedef enum timer_ic_input_select { + TIMER_IC_INPUT_DEFAULT = TIMER_CCMR_CCS_INPUT_TI1, + TIMER_IC_INPUT_SWITCH = TIMER_CCMR_CCS_INPUT_TI2, + TIMER_IC_INPUT_TRC = TIMER_CCMR_CCS_INPUT_TRC, +} timer_ic_input_select; -/** Deprecated. Use TIMER_CCMR1_CC4S_OUTPUT instead. */ -#define TIMER_CCMR1_CC4S_OUTPUT TIMER_CCMR2_CC4S_OUTPUT -/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI1 instead. */ -#define TIMER_CCMR1_CC4S_INPUT_TI1 TIMER_CCMR2_CC4S_INPUT_TI1 -/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI2 instead. */ -#define TIMER_CCMR1_CC4S_INPUT_TI2 TIMER_CCMR2_CC4S_INPUT_TI2 -/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TRC instead. */ -#define TIMER_CCMR1_CC4S_INPUT_TRC TIMER_CCMR2_CC4S_INPUT_TRC -/** Deprecated. Use TIMER_CCMR2_IC4F instead. */ -#define TIMER_CCMR2_IC2F TIMER_CCMR2_IC4F -/** Deprecated. Use TIMER_CCMR2_IC4PSC instead. */ -#define TIMER_CCMR2_IC2PSC TIMER_CCMR2_IC4PSC -/** Deprecated. Use TIMER_CCMR2_IC3F instead. */ -#define TIMER_CCMR2_IC1F TIMER_CCMR2_IC3F -/** Deprecated. Use TIMER_CCMR2_IC3PSC instead. */ -#define TIMER_CCMR2_IC1PSC TIMER_CCMR2_IC3PSC -/** Deprecated. Use TIMER_CCMR1_CC3S_OUTPUT instead. */ -#define TIMER_CCMR1_CC3S_OUTPUT TIMER_CCMR2_CC3S_OUTPUT -/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI1 instead. */ -#define TIMER_CCMR1_CC3S_INPUT_TI1 TIMER_CCMR2_CC3S_INPUT_TI1 -/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI2 instead. */ -#define TIMER_CCMR1_CC3S_INPUT_TI2 TIMER_CCMR2_CC3S_INPUT_TI2 -/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TRC instead. */ -#define TIMER_CCMR1_CC3S_INPUT_TRC TIMER_CCMR2_CC3S_INPUT_TRC +extern void input_capture_mode(timer_dev *dev, uint8 channel, timer_ic_input_select input); -/** Deprecated. Use TIMER_DCR_DBL_1_XFER instead. */ -#define TIMER_DCR_DBL_1BYTE TIMER_DCR_DBL_1_XFER -/** Deprecated. Use TIMER_DCR_DBL_2_XFER instead. */ -#define TIMER_DCR_DBL_2BYTE TIMER_DCR_DBL_2_XFER -/** Deprecated. Use TIMER_DCR_DBL_3_XFER instead. */ -#define TIMER_DCR_DBL_3BYTE TIMER_DCR_DBL_3_XFER -/** Deprecated. Use TIMER_DCR_DBL_4_XFER instead. */ -#define TIMER_DCR_DBL_4BYTE TIMER_DCR_DBL_4_XFER -/** Deprecated. Use TIMER_DCR_DBL_5_XFER instead. */ -#define TIMER_DCR_DBL_5BYTE TIMER_DCR_DBL_5_XFER -/** Deprecated. Use TIMER_DCR_DBL_6_XFER instead. */ -#define TIMER_DCR_DBL_6BYTE TIMER_DCR_DBL_6_XFER -/** Deprecated. Use TIMER_DCR_DBL_7_XFER instead. */ -#define TIMER_DCR_DBL_7BYTE TIMER_DCR_DBL_7_XFER -/** Deprecated. Use TIMER_DCR_DBL_8_XFER instead. */ -#define TIMER_DCR_DBL_8BYTE TIMER_DCR_DBL_8_XFER -/** Deprecated. Use TIMER_DCR_DBL_9_XFER instead. */ -#define TIMER_DCR_DBL_9BYTE TIMER_DCR_DBL_9_XFER -/** Deprecated. Use TIMER_DCR_DBL_10_XFER instead. */ -#define TIMER_DCR_DBL_10BYTE TIMER_DCR_DBL_10_XFER -/** Deprecated. Use TIMER_DCR_DBL_11_XFER instead. */ -#define TIMER_DCR_DBL_11BYTE TIMER_DCR_DBL_11_XFER -/** Deprecated. Use TIMER_DCR_DBL_12_XFER instead. */ -#define TIMER_DCR_DBL_12BYTE TIMER_DCR_DBL_12_XFER -/** Deprecated. Use TIMER_DCR_DBL_13_XFER instead. */ -#define TIMER_DCR_DBL_13BYTE TIMER_DCR_DBL_13_XFER -/** Deprecated. Use TIMER_DCR_DBL_14_XFER instead. */ -#define TIMER_DCR_DBL_14BYTE TIMER_DCR_DBL_14_XFER -/** Deprecated. Use TIMER_DCR_DBL_15_XFER instead. */ -#define TIMER_DCR_DBL_15BYTE TIMER_DCR_DBL_15_XFER -/** Deprecated. Use TIMER_DCR_DBL_16_XFER instead. */ -#define TIMER_DCR_DBL_16BYTE TIMER_DCR_DBL_16_XFER -/** Deprecated. Use TIMER_DCR_DBL_17_XFER instead. */ -#define TIMER_DCR_DBL_17BYTE TIMER_DCR_DBL_17_XFER -/** Deprecated. Use TIMER_DCR_DBL_18_XFER instead. */ -#define TIMER_DCR_DBL_18BYTE TIMER_DCR_DBL_18_XFER #ifdef __cplusplus } // extern "C" diff --git a/STM32F1/system/libmaple/include/libmaple/usart.h b/STM32F1/system/libmaple/include/libmaple/usart.h index fa7c7fb..9a868df 100644 --- a/STM32F1/system/libmaple/include/libmaple/usart.h +++ b/STM32F1/system/libmaple/include/libmaple/usart.h @@ -53,13 +53,13 @@ extern "C"{ /** USART register map type */ typedef struct usart_reg_map { - __io uint32 SR; /**< Status register */ - __io uint32 DR; /**< Data register */ - __io uint32 BRR; /**< Baud rate register */ - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 CR3; /**< Control register 3 */ - __io uint32 GTPR; /**< Guard time and prescaler register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 DR; /**< Data register */ + __IO uint32 BRR; /**< Baud rate register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 CR3; /**< Control register 3 */ + __IO uint32 GTPR; /**< Guard time and prescaler register */ } usart_reg_map; /* @@ -439,8 +439,8 @@ static inline void usart_disable_all(void) { /** * @brief Transmit one character on a serial port. * - * This function blocks until the character has been successfully - * transmitted. + * This function blocks until the character has been queued + * for transmission. * * @param dev Serial port to send on. * @param byte Byte to transmit. diff --git a/STM32F1/system/libmaple/include/libmaple/usb.h b/STM32F1/system/libmaple/include/libmaple/usb.h index ea24030..1ea06e9 100644 --- a/STM32F1/system/libmaple/include/libmaple/usb.h +++ b/STM32F1/system/libmaple/include/libmaple/usb.h @@ -157,6 +157,8 @@ typedef struct usblib_dev { extern usblib_dev *USBLIB; +void usb_power_off(void); + void usb_init_usblib(usblib_dev *dev, void (**ep_int_in)(void), void (**ep_int_out)(void)); diff --git a/STM32F1/system/libmaple/include/libmaple/usb_cdcacm.h b/STM32F1/system/libmaple/include/libmaple/usb_cdcacm.h index 62c9181..53551a7 100644 --- a/STM32F1/system/libmaple/include/libmaple/usb_cdcacm.h +++ b/STM32F1/system/libmaple/include/libmaple/usb_cdcacm.h @@ -129,10 +129,13 @@ uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len); uint32 usb_cdcacm_data_available(void); /* in RX buffer */ uint16 usb_cdcacm_get_pending(void); uint8 usb_cdcacm_is_transmitting(void); +int usb_cdcacm_tx_available(); uint8 usb_cdcacm_get_dtr(void); uint8 usb_cdcacm_get_rts(void); + + typedef struct usb_cdcacm_line_coding { uint32 dwDTERate; /* Baud rate */ diff --git a/STM32F1/system/libmaple/include/util/atomic.h b/STM32F1/system/libmaple/include/util/atomic.h new file mode 100644 index 0000000..db5e489 --- /dev/null +++ b/STM32F1/system/libmaple/include/util/atomic.h @@ -0,0 +1,69 @@ +/* +* This is port of Dean Camera's ATOMIC_BLOCK macros for AVR to ARM Cortex M3 +* v1.0 +* Mark Pendrith, Nov 27, 2012. +* +* From Mark: +* >When I ported the macros I emailed Dean to ask what attribution would be +* >appropriate, and here is his response: +* > +* >>Mark, +* >>I think it's great that you've ported the macros; consider them +* >>public domain, to do with whatever you wish. I hope you find them useful. +* >> +* >>Cheers! +* >>- Dean +*/ + +#ifndef _CORTEX_M3_ATOMIC_H_ +#define _CORTEX_M3_ATOMIC_H_ + +static __inline__ uint32_t __get_primask(void) \ +{ uint32_t primask = 0; \ + __asm__ volatile ("MRS %[result], PRIMASK\n\t":[result]"=r"(primask)::); \ + return primask; } // returns 0 if interrupts enabled, 1 if disabled + +static __inline__ void __set_primask(uint32_t setval) \ +{ __asm__ volatile ("MSR PRIMASK, %[value]\n\t""dmb\n\t""dsb\n\t""isb\n\t"::[value]"r"(setval):); \ + __asm__ volatile ("" ::: "memory");} + +static __inline__ uint32_t __iSeiRetVal(void) \ +{ __asm__ volatile ("CPSIE i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \ + __asm__ volatile ("" ::: "memory"); return 1; } + +static __inline__ uint32_t __iCliRetVal(void) \ +{ __asm__ volatile ("CPSID i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \ + __asm__ volatile ("" ::: "memory"); return 1; } + +static __inline__ void __iSeiParam(const uint32_t *__s) \ +{ __asm__ volatile ("CPSIE i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \ + __asm__ volatile ("" ::: "memory"); (void)__s; } + +static __inline__ void __iCliParam(const uint32_t *__s) \ +{ __asm__ volatile ("CPSID i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \ + __asm__ volatile ("" ::: "memory"); (void)__s; } + +static __inline__ void __iRestore(const uint32_t *__s) \ +{ __set_primask(*__s); __asm__ volatile ("dmb\n\t""dsb\n\t""isb\n\t"); \ + __asm__ volatile ("" ::: "memory"); } + + +#define ATOMIC_BLOCK(type) \ +for ( type, __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0 ) + +#define ATOMIC_RESTORESTATE \ +uint32_t primask_save __attribute__((__cleanup__(__iRestore))) = __get_primask() + +#define ATOMIC_FORCEON \ +uint32_t primask_save __attribute__((__cleanup__(__iSeiParam))) = 0 + +#define NONATOMIC_BLOCK(type) \ +for ( type, __ToDo = __iSeiRetVal(); __ToDo ; __ToDo = 0 ) + +#define NONATOMIC_RESTORESTATE \ +uint32_t primask_save __attribute__((__cleanup__(__iRestore))) = __get_primask() + +#define NONATOMIC_FORCEOFF \ +uint32_t primask_save __attribute__((__cleanup__(__iCliParam))) = 0 + +#endif diff --git a/STM32F1/system/libmaple/rcc_private.h b/STM32F1/system/libmaple/rcc_private.h index afb8a31..a47afca 100644 --- a/STM32F1/system/libmaple/rcc_private.h +++ b/STM32F1/system/libmaple/rcc_private.h @@ -40,16 +40,16 @@ struct rcc_dev_info { extern const struct rcc_dev_info rcc_dev_table[]; -static inline void rcc_do_clk_enable(__io uint32** enable_regs, +static inline void rcc_do_clk_enable(__IO uint32** enable_regs, rcc_clk_id id) { - __io uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; + __IO uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; uint8 line_num = rcc_dev_table[id].line_num; bb_peri_set_bit(enable_reg, line_num, 1); } -static inline void rcc_do_reset_dev(__io uint32** reset_regs, +static inline void rcc_do_reset_dev(__IO uint32** reset_regs, rcc_clk_id id) { - __io uint32 *reset_reg = reset_regs[rcc_dev_clk(id)]; + __IO uint32 *reset_reg = reset_regs[rcc_dev_clk(id)]; uint8 line_num = rcc_dev_table[id].line_num; bb_peri_set_bit(reset_reg, line_num, 1); bb_peri_set_bit(reset_reg, line_num, 0); @@ -64,9 +64,9 @@ static inline void rcc_do_set_prescaler(const uint32 *masks, RCC_BASE->CFGR = cfgr; } -static inline void rcc_do_clk_disable(__io uint32** enable_regs, +static inline void rcc_do_clk_disable(__IO uint32** enable_regs, rcc_clk_id id) { - __io uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; + __IO uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; uint8 line_num = rcc_dev_table[id].line_num; bb_peri_set_bit(enable_reg, line_num, 0); } diff --git a/STM32F1/system/libmaple/stm32f1/include/series/dac.h b/STM32F1/system/libmaple/stm32f1/include/series/dac.h index c0d026b..5bf4b9e 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/dac.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/dac.h @@ -40,28 +40,28 @@ extern "C"{ /** STM32F1 DAC register map type. */ typedef struct dac_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 SWTRIGR; /**< Software trigger register */ - __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + __IO uint32 CR; /**< Control register */ + __IO uint32 SWTRIGR; /**< Software trigger register */ + __IO uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data holding register */ - __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + __IO uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data holding register */ - __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + __IO uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data holding register */ - __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + __IO uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data holding register */ - __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + __IO uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data holding register */ - __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + __IO uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data holding register */ - __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + __IO uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data holding register */ - __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + __IO uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data holding register */ - __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + __IO uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding register */ - __io uint32 DOR1; /**< Channel 1 data output register */ - __io uint32 DOR2; /**< Channel 2 data output register */ + __IO uint32 DOR1; /**< Channel 1 data output register */ + __IO uint32 DOR2; /**< Channel 2 data output register */ } dac_reg_map; #ifdef __cplusplus diff --git a/STM32F1/system/libmaple/stm32f1/include/series/dma.h b/STM32F1/system/libmaple/stm32f1/include/series/dma.h index bedb602..5260f8e 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/dma.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/dma.h @@ -57,42 +57,42 @@ extern "C"{ * only supports channels 1--5. */ typedef struct dma_reg_map { - __io uint32 ISR; /**< Interrupt status register */ - __io uint32 IFCR; /**< Interrupt flag clear register */ - __io uint32 CCR1; /**< Channel 1 configuration register */ - __io uint32 CNDTR1; /**< Channel 1 number of data register */ - __io uint32 CPAR1; /**< Channel 1 peripheral address register */ - __io uint32 CMAR1; /**< Channel 1 memory address register */ + __IO uint32 ISR; /**< Interrupt status register */ + __IO uint32 IFCR; /**< Interrupt flag clear register */ + __IO uint32 CCR1; /**< Channel 1 configuration register */ + __IO uint32 CNDTR1; /**< Channel 1 number of data register */ + __IO uint32 CPAR1; /**< Channel 1 peripheral address register */ + __IO uint32 CMAR1; /**< Channel 1 memory address register */ const uint32 RESERVED1; /**< Reserved. */ - __io uint32 CCR2; /**< Channel 2 configuration register */ - __io uint32 CNDTR2; /**< Channel 2 number of data register */ - __io uint32 CPAR2; /**< Channel 2 peripheral address register */ - __io uint32 CMAR2; /**< Channel 2 memory address register */ + __IO uint32 CCR2; /**< Channel 2 configuration register */ + __IO uint32 CNDTR2; /**< Channel 2 number of data register */ + __IO uint32 CPAR2; /**< Channel 2 peripheral address register */ + __IO uint32 CMAR2; /**< Channel 2 memory address register */ const uint32 RESERVED2; /**< Reserved. */ - __io uint32 CCR3; /**< Channel 3 configuration register */ - __io uint32 CNDTR3; /**< Channel 3 number of data register */ - __io uint32 CPAR3; /**< Channel 3 peripheral address register */ - __io uint32 CMAR3; /**< Channel 3 memory address register */ + __IO uint32 CCR3; /**< Channel 3 configuration register */ + __IO uint32 CNDTR3; /**< Channel 3 number of data register */ + __IO uint32 CPAR3; /**< Channel 3 peripheral address register */ + __IO uint32 CMAR3; /**< Channel 3 memory address register */ const uint32 RESERVED3; /**< Reserved. */ - __io uint32 CCR4; /**< Channel 4 configuration register */ - __io uint32 CNDTR4; /**< Channel 4 number of data register */ - __io uint32 CPAR4; /**< Channel 4 peripheral address register */ - __io uint32 CMAR4; /**< Channel 4 memory address register */ + __IO uint32 CCR4; /**< Channel 4 configuration register */ + __IO uint32 CNDTR4; /**< Channel 4 number of data register */ + __IO uint32 CPAR4; /**< Channel 4 peripheral address register */ + __IO uint32 CMAR4; /**< Channel 4 memory address register */ const uint32 RESERVED4; /**< Reserved. */ - __io uint32 CCR5; /**< Channel 5 configuration register */ - __io uint32 CNDTR5; /**< Channel 5 number of data register */ - __io uint32 CPAR5; /**< Channel 5 peripheral address register */ - __io uint32 CMAR5; /**< Channel 5 memory address register */ + __IO uint32 CCR5; /**< Channel 5 configuration register */ + __IO uint32 CNDTR5; /**< Channel 5 number of data register */ + __IO uint32 CPAR5; /**< Channel 5 peripheral address register */ + __IO uint32 CMAR5; /**< Channel 5 memory address register */ const uint32 RESERVED5; /**< Reserved. */ - __io uint32 CCR6; /**< Channel 6 configuration register */ - __io uint32 CNDTR6; /**< Channel 6 number of data register */ - __io uint32 CPAR6; /**< Channel 6 peripheral address register */ - __io uint32 CMAR6; /**< Channel 6 memory address register */ + __IO uint32 CCR6; /**< Channel 6 configuration register */ + __IO uint32 CNDTR6; /**< Channel 6 number of data register */ + __IO uint32 CPAR6; /**< Channel 6 peripheral address register */ + __IO uint32 CMAR6; /**< Channel 6 memory address register */ const uint32 RESERVED6; /**< Reserved. */ - __io uint32 CCR7; /**< Channel 7 configuration register */ - __io uint32 CNDTR7; /**< Channel 7 number of data register */ - __io uint32 CPAR7; /**< Channel 7 peripheral address register */ - __io uint32 CMAR7; /**< Channel 7 memory address register */ + __IO uint32 CCR7; /**< Channel 7 configuration register */ + __IO uint32 CNDTR7; /**< Channel 7 number of data register */ + __IO uint32 CPAR7; /**< Channel 7 peripheral address register */ + __IO uint32 CMAR7; /**< Channel 7 memory address register */ const uint32 RESERVED7; /**< Reserved. */ } dma_reg_map; @@ -107,10 +107,10 @@ typedef struct dma_reg_map { * @see dma_tube_regs() */ typedef struct dma_tube_reg_map { - __io uint32 CCR; /**< Channel configuration register */ - __io uint32 CNDTR; /**< Channel number of data register */ - __io uint32 CPAR; /**< Channel peripheral address register */ - __io uint32 CMAR; /**< Channel memory address register */ + __IO uint32 CCR; /**< Channel configuration register */ + __IO uint32 CNDTR; /**< Channel number of data register */ + __IO uint32 CPAR; /**< Channel peripheral address register */ + __IO uint32 CMAR; /**< Channel memory address register */ } dma_tube_reg_map; /** DMA1 channel 1 register map base pointer */ @@ -152,7 +152,7 @@ typedef struct dma_tube_reg_map { #define DMA_ISR_TEIF (1 << DMA_ISR_TEIF_BIT) #define DMA_ISR_HTIF (1 << DMA_ISR_HTIF_BIT) -#define DMA_ISR_TCID (1 << DMA_ISR_TCIF_BIT) +#define DMA_ISR_TCIF (1 << DMA_ISR_TCIF_BIT) #define DMA_ISR_GIF (1 << DMA_ISR_GIF_BIT) #define DMA_ISR_TEIF7_BIT 27 @@ -516,7 +516,7 @@ typedef enum dma_request_src { #define DMA_CHANNEL_NREGS 5 /* accounts for reserved word */ static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, dma_tube tube) { - __io uint32 *ccr1 = &dev->regs->CCR1; + __IO uint32 *ccr1 = &dev->regs->CCR1; return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (tube - 1)); } @@ -538,6 +538,10 @@ static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) { dev->regs->IFCR = (1U << (4 * (tube - 1))); } +static inline uint16 dma_get_count(dma_dev *dev, dma_tube tube) { + return dma_channel_regs(dev, tube)->CNDTR; +} + /** * @brief Deprecated * STM32F1 mode flags for dma_setup_xfer(). Use dma_tube_cfg() instead. @@ -559,12 +563,11 @@ typedef enum dma_mode_flags { * * (It's not possible to fully configure a DMA stream on F2 with just * this information, so this interface is too tied to the F1.) */ -__deprecated void dma_setup_transfer(dma_dev *dev, dma_channel channel, - __io void *peripheral_address, + __IO void *peripheral_address, dma_xfer_size peripheral_size, - __io void *memory_address, + __IO void *memory_address, dma_xfer_size memory_size, uint32 mode); diff --git a/STM32F1/system/libmaple/stm32f1/include/series/flash.h b/STM32F1/system/libmaple/stm32f1/include/series/flash.h index 24efb0b..0ed43c6 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/flash.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/flash.h @@ -48,14 +48,14 @@ extern "C"{ /** @brief STM32F1 Flash register map type */ typedef struct flash_reg_map { - __io uint32 ACR; /**< Access control register */ - __io uint32 KEYR; /**< Key register */ - __io uint32 OPTKEYR; /**< OPTKEY register */ - __io uint32 SR; /**< Status register */ - __io uint32 CR; /**< Control register */ - __io uint32 AR; /**< Address register */ - __io uint32 OBR; /**< Option byte register */ - __io uint32 WRPR; /**< Write protection register */ + __IO uint32 ACR; /**< Access control register */ + __IO uint32 KEYR; /**< Key register */ + __IO uint32 OPTKEYR; /**< OPTKEY register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 CR; /**< Control register */ + __IO uint32 AR; /**< Address register */ + __IO uint32 OBR; /**< Option byte register */ + __IO uint32 WRPR; /**< Write protection register */ } flash_reg_map; #define FLASH_BASE ((struct flash_reg_map*)0x40022000) @@ -132,7 +132,7 @@ typedef struct flash_reg_map { * Series-specific configuration values. */ -#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_2 +#define FLASH_SAFE_WAIT_STATES (F_CPU > 48000000 ? FLASH_WAIT_STATE_2 : F_CPU > 24000000 ? FLASH_WAIT_STATE_1 : FLASH_WAIT_STATE_0) /* Flash memory features available via ACR */ enum { diff --git a/STM32F1/system/libmaple/stm32f1/include/series/gpio.h b/STM32F1/system/libmaple/stm32f1/include/series/gpio.h index aff639b..c40b21a 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/gpio.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/gpio.h @@ -31,6 +31,7 @@ * General purpose I/O (GPIO) and Alternate Function I/O (AFIO). */ + #ifndef _LIBMAPLE_STM32F1_GPIO_H_ #define _LIBMAPLE_STM32F1_GPIO_H_ @@ -48,15 +49,16 @@ extern "C"{ /** GPIO register map type */ typedef struct gpio_reg_map { - __io uint32 CRL; /**< Port configuration register low */ - __io uint32 CRH; /**< Port configuration register high */ - __io uint32 IDR; /**< Port input data register */ - __io uint32 ODR; /**< Port output data register */ - __io uint32 BSRR; /**< Port bit set/reset register */ - __io uint32 BRR; /**< Port bit reset register */ - __io uint32 LCKR; /**< Port configuration lock register */ + __IO uint32 CRL; /**< Port configuration register low */ + __IO uint32 CRH; /**< Port configuration register high */ + __IO uint32 IDR; /**< Port input data register */ + __IO uint32 ODR; /**< Port output data register */ + __IO uint32 BSRR; /**< Port bit set/reset register */ + __IO uint32 BRR; /**< Port bit reset register */ + __IO uint32 LCKR; /**< Port configuration lock register */ } gpio_reg_map; + struct gpio_dev; extern struct gpio_dev gpioa; extern struct gpio_dev* const GPIOA; @@ -66,7 +68,7 @@ extern struct gpio_dev gpioc; extern struct gpio_dev* const GPIOC; extern struct gpio_dev gpiod; extern struct gpio_dev* const GPIOD; -#ifdef STM32_HIGH_DENSITY +#if STM32_NR_GPIO_PORTS > 4 extern struct gpio_dev gpioe; extern struct gpio_dev* const GPIOE; extern struct gpio_dev gpiof; @@ -145,13 +147,13 @@ typedef enum gpio_pin_mode { /** AFIO register map */ typedef struct afio_reg_map { - __io uint32 EVCR; /**< Event control register. */ - __io uint32 MAPR; /**< AF remap and debug I/O configuration register. */ - __io uint32 EXTICR1; /**< External interrupt configuration register 1. */ - __io uint32 EXTICR2; /**< External interrupt configuration register 2. */ - __io uint32 EXTICR3; /**< External interrupt configuration register 3. */ - __io uint32 EXTICR4; /**< External interrupt configuration register 4. */ - __io uint32 MAPR2; /**< + __IO uint32 EVCR; /**< Event control register. */ + __IO uint32 MAPR; /**< AF remap and debug I/O configuration register. */ + __IO uint32 EXTICR1; /**< External interrupt configuration register 1. */ + __IO uint32 EXTICR2; /**< External interrupt configuration register 2. */ + __IO uint32 EXTICR3; /**< External interrupt configuration register 3. */ + __IO uint32 EXTICR4; /**< External interrupt configuration register 4. */ + __IO uint32 MAPR2; /**< * AF remap and debug I/O configuration register 2. */ } afio_reg_map; @@ -404,7 +406,7 @@ typedef enum afio_debug_cfg { * @see afio_debug_cfg */ static inline void afio_cfg_debug_ports(afio_debug_cfg config) { - __io uint32 *mapr = &AFIO_BASE->MAPR; + __IO uint32 *mapr = &AFIO_BASE->MAPR; *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; } diff --git a/STM32F1/system/libmaple/stm32f1/include/series/i2c.h b/STM32F1/system/libmaple/stm32f1/include/series/i2c.h index f407955..3565503 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/i2c.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/i2c.h @@ -59,7 +59,7 @@ extern i2c_dev* const I2C2; * For internal use */ -static inline uint32 _i2c_bus_clk(i2c_dev *dev) { +static inline uint32 _i2c_bus_clk(i2c_dev *dev __attribute__((unused))) { /* Both I2C peripherals are on APB1 */ return STM32_PCLK1 / (1000 * 1000); } diff --git a/STM32F1/system/libmaple/stm32f1/include/series/rcc.h b/STM32F1/system/libmaple/stm32f1/include/series/rcc.h index f40dcba..e6a4a5b 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/rcc.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/rcc.h @@ -46,16 +46,16 @@ extern "C"{ /** STM32F1 RCC register map type */ typedef struct rcc_reg_map { - __io uint32 CR; /**< Clock control register */ - __io uint32 CFGR; /**< Clock configuration register */ - __io uint32 CIR; /**< Clock interrupt register */ - __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ - __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ - __io uint32 AHBENR; /**< AHB peripheral clock enable register */ - __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ - __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ - __io uint32 BDCR; /**< Backup domain control register */ - __io uint32 CSR; /**< Control/status register */ + __IO uint32 CR; /**< Clock control register */ + __IO uint32 CFGR; /**< Clock configuration register */ + __IO uint32 CIR; /**< Clock interrupt register */ + __IO uint32 APB2RSTR; /**< APB2 peripheral reset register */ + __IO uint32 APB1RSTR; /**< APB1 peripheral reset register */ + __IO uint32 AHBENR; /**< AHB peripheral clock enable register */ + __IO uint32 APB2ENR; /**< APB2 peripheral clock enable register */ + __IO uint32 APB1ENR; /**< APB1 peripheral clock enable register */ + __IO uint32 BDCR; /**< Backup domain control register */ + __IO uint32 CSR; /**< Control/status register */ } rcc_reg_map; #define RCC_BASE ((struct rcc_reg_map*)0x40021000) diff --git a/STM32F1/system/libmaple/stm32f1/include/series/stm32.h b/STM32F1/system/libmaple/stm32f1/include/series/stm32.h index 9386dc3..1346885 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/stm32.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/stm32.h @@ -185,12 +185,20 @@ extern "C" { # elif defined(STM32_HIGH_DENSITY) # define STM32_NR_INTERRUPTS 60 # define STM32_TIMER_MASK 0x1FE /* TIMER1--TIMER8 */ -# define STM32_HAVE_FSMC 1 +# if STM32_NR_GPIO_PORTS > 4 +# define STM32_HAVE_FSMC 1 +# else +# define STM32_HAVE_FSMC 0 +# endif # define STM32_HAVE_DAC 1 # elif defined(STM32_XL_DENSITY) # define STM32_NR_INTERRUPTS 60 # define STM32_TIMER_MASK 0x7FFE /* TIMER1--TIMER14 */ -# define STM32_HAVE_FSMC 1 +# if STM32_NR_GPIO_PORTS > 4 +# define STM32_HAVE_FSMC 1 +# else +# define STM32_HAVE_FSMC 0 +# endif # define STM32_HAVE_DAC 1 # endif diff --git a/STM32F1/system/libmaple/stm32f1/include/series/timer.h b/STM32F1/system/libmaple/stm32f1/include/series/timer.h index 8c1f8f4..c07b7b4 100644 --- a/STM32F1/system/libmaple/stm32f1/include/series/timer.h +++ b/STM32F1/system/libmaple/stm32f1/include/series/timer.h @@ -41,26 +41,26 @@ /** STM32F1 general purpose timer register map type */ typedef struct timer_gen_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SMCR; /**< Slave mode control register */ + __IO uint32 DIER; /**< DMA/Interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ + __IO uint32 CCMR1; /**< Capture/compare mode register 1 */ + __IO uint32 CCMR2; /**< Capture/compare mode register 2 */ + __IO uint32 CCER; /**< Capture/compare enable register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ const uint32 RESERVED1; /**< Reserved */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ + __IO uint32 CCR1; /**< Capture/compare register 1 */ + __IO uint32 CCR2; /**< Capture/compare register 2 */ + __IO uint32 CCR3; /**< Capture/compare register 3 */ + __IO uint32 CCR4; /**< Capture/compare register 4 */ const uint32 RESERVED2; /**< Reserved */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ + __IO uint32 DCR; /**< DMA control register */ + __IO uint32 DMAR; /**< DMA address for full transfer */ } timer_gen_reg_map; struct timer_adv_reg_map; diff --git a/STM32F1/system/libmaple/stm32f2/include/series/adc.h b/STM32F1/system/libmaple/stm32f2/include/series/adc.h index 175fe11..3bfa2cc 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/adc.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/adc.h @@ -49,9 +49,9 @@ extern const struct adc_dev *ADC3; /** ADC common register map type */ typedef struct adc_common_reg_map { - __io uint32 CSR; /**< Common status register */ - __io uint32 CCR; /**< Common control register */ - __io uint32 CDR; /**< + __IO uint32 CSR; /**< Common status register */ + __IO uint32 CCR; /**< Common control register */ + __IO uint32 CDR; /**< * @brief Common regular data register * for dual and triple modes */ } adc_common_reg_map; diff --git a/STM32F1/system/libmaple/stm32f2/include/series/dac.h b/STM32F1/system/libmaple/stm32f2/include/series/dac.h index 0a578ca..0d74a16 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/dac.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/dac.h @@ -44,29 +44,29 @@ extern "C"{ /** STM32F2 DAC register map type. */ typedef struct dac_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 SWTRIGR; /**< Software trigger register */ - __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + __IO uint32 CR; /**< Control register */ + __IO uint32 SWTRIGR; /**< Software trigger register */ + __IO uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data holding register */ - __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + __IO uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data holding register */ - __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + __IO uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data holding register */ - __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + __IO uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data holding register */ - __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + __IO uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data holding register */ - __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + __IO uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data holding register */ - __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + __IO uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data holding register */ - __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + __IO uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data holding register */ - __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + __IO uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding register */ - __io uint32 DOR1; /**< Channel 1 data output register */ - __io uint32 DOR2; /**< Channel 2 data output register */ - __io uint32 SR; /**< Status register */ + __IO uint32 DOR1; /**< Channel 1 data output register */ + __IO uint32 DOR2; /**< Channel 2 data output register */ + __IO uint32 SR; /**< Status register */ } dac_reg_map; /* diff --git a/STM32F1/system/libmaple/stm32f2/include/series/dma.h b/STM32F1/system/libmaple/stm32f2/include/series/dma.h index 56725e5..4c86443 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/dma.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/dma.h @@ -51,66 +51,66 @@ typedef struct dma_reg_map { /* Isn't it nice how on F1, it's CCR1, but on F2, it's S1CR? */ /* Global DMA registers */ - __io uint32 LISR; /**< Low interrupt status register */ - __io uint32 HISR; /**< High interrupt status register */ - __io uint32 LIFCR; /**< Low interrupt flag clear register */ - __io uint32 HIFCR; /**< High interrupt flag clear register */ + __IO uint32 LISR; /**< Low interrupt status register */ + __IO uint32 HISR; /**< High interrupt status register */ + __IO uint32 LIFCR; /**< Low interrupt flag clear register */ + __IO uint32 HIFCR; /**< High interrupt flag clear register */ /* Stream 0 registers */ - __io uint32 S0CR; /**< Stream 0 control register */ - __io uint32 S0NDTR; /**< Stream 0 number of data register */ - __io uint32 S0PAR; /**< Stream 0 peripheral address register */ - __io uint32 S0M0AR; /**< Stream 0 memory 0 address register */ - __io uint32 S0M1AR; /**< Stream 0 memory 1 address register */ - __io uint32 S0FCR; /**< Stream 0 FIFO control register */ + __IO uint32 S0CR; /**< Stream 0 control register */ + __IO uint32 S0NDTR; /**< Stream 0 number of data register */ + __IO uint32 S0PAR; /**< Stream 0 peripheral address register */ + __IO uint32 S0M0AR; /**< Stream 0 memory 0 address register */ + __IO uint32 S0M1AR; /**< Stream 0 memory 1 address register */ + __IO uint32 S0FCR; /**< Stream 0 FIFO control register */ /* Stream 1 registers */ - __io uint32 S1CR; /**< Stream 1 control register */ - __io uint32 S1NDTR; /**< Stream 1 number of data register */ - __io uint32 S1PAR; /**< Stream 1 peripheral address register */ - __io uint32 S1M0AR; /**< Stream 1 memory 0 address register */ - __io uint32 S1M1AR; /**< Stream 1 memory 1 address register */ - __io uint32 S1FCR; /**< Stream 1 FIFO control register */ + __IO uint32 S1CR; /**< Stream 1 control register */ + __IO uint32 S1NDTR; /**< Stream 1 number of data register */ + __IO uint32 S1PAR; /**< Stream 1 peripheral address register */ + __IO uint32 S1M0AR; /**< Stream 1 memory 0 address register */ + __IO uint32 S1M1AR; /**< Stream 1 memory 1 address register */ + __IO uint32 S1FCR; /**< Stream 1 FIFO control register */ /* Stream 2 registers */ - __io uint32 S2CR; /**< Stream 2 control register */ - __io uint32 S2NDTR; /**< Stream 2 number of data register */ - __io uint32 S2PAR; /**< Stream 2 peripheral address register */ - __io uint32 S2M0AR; /**< Stream 2 memory 0 address register */ - __io uint32 S2M1AR; /**< Stream 2 memory 1 address register */ - __io uint32 S2FCR; /**< Stream 2 FIFO control register */ + __IO uint32 S2CR; /**< Stream 2 control register */ + __IO uint32 S2NDTR; /**< Stream 2 number of data register */ + __IO uint32 S2PAR; /**< Stream 2 peripheral address register */ + __IO uint32 S2M0AR; /**< Stream 2 memory 0 address register */ + __IO uint32 S2M1AR; /**< Stream 2 memory 1 address register */ + __IO uint32 S2FCR; /**< Stream 2 FIFO control register */ /* Stream 3 registers */ - __io uint32 S3CR; /**< Stream 3 control register */ - __io uint32 S3NDTR; /**< Stream 3 number of data register */ - __io uint32 S3PAR; /**< Stream 3 peripheral address register */ - __io uint32 S3M0AR; /**< Stream 3 memory 0 address register */ - __io uint32 S3M1AR; /**< Stream 3 memory 1 address register */ - __io uint32 S3FCR; /**< Stream 3 FIFO control register */ + __IO uint32 S3CR; /**< Stream 3 control register */ + __IO uint32 S3NDTR; /**< Stream 3 number of data register */ + __IO uint32 S3PAR; /**< Stream 3 peripheral address register */ + __IO uint32 S3M0AR; /**< Stream 3 memory 0 address register */ + __IO uint32 S3M1AR; /**< Stream 3 memory 1 address register */ + __IO uint32 S3FCR; /**< Stream 3 FIFO control register */ /* Stream 4 registers */ - __io uint32 S4CR; /**< Stream 4 control register */ - __io uint32 S4NDTR; /**< Stream 4 number of data register */ - __io uint32 S4PAR; /**< Stream 4 peripheral address register */ - __io uint32 S4M0AR; /**< Stream 4 memory 0 address register */ - __io uint32 S4M1AR; /**< Stream 4 memory 1 address register */ - __io uint32 S4FCR; /**< Stream 4 FIFO control register */ + __IO uint32 S4CR; /**< Stream 4 control register */ + __IO uint32 S4NDTR; /**< Stream 4 number of data register */ + __IO uint32 S4PAR; /**< Stream 4 peripheral address register */ + __IO uint32 S4M0AR; /**< Stream 4 memory 0 address register */ + __IO uint32 S4M1AR; /**< Stream 4 memory 1 address register */ + __IO uint32 S4FCR; /**< Stream 4 FIFO control register */ /* Stream 5 registers */ - __io uint32 S5CR; /**< Stream 5 control register */ - __io uint32 S5NDTR; /**< Stream 5 number of data register */ - __io uint32 S5PAR; /**< Stream 5 peripheral address register */ - __io uint32 S5M0AR; /**< Stream 5 memory 0 address register */ - __io uint32 S5M1AR; /**< Stream 5 memory 1 address register */ - __io uint32 S5FCR; /**< Stream 5 FIFO control register */ + __IO uint32 S5CR; /**< Stream 5 control register */ + __IO uint32 S5NDTR; /**< Stream 5 number of data register */ + __IO uint32 S5PAR; /**< Stream 5 peripheral address register */ + __IO uint32 S5M0AR; /**< Stream 5 memory 0 address register */ + __IO uint32 S5M1AR; /**< Stream 5 memory 1 address register */ + __IO uint32 S5FCR; /**< Stream 5 FIFO control register */ /* Stream 6 registers */ - __io uint32 S6CR; /**< Stream 6 control register */ - __io uint32 S6NDTR; /**< Stream 6 number of data register */ - __io uint32 S6PAR; /**< Stream 6 peripheral address register */ - __io uint32 S6M0AR; /**< Stream 6 memory 0 address register */ - __io uint32 S6M1AR; /**< Stream 6 memory 1 address register */ - __io uint32 S6FCR; /**< Stream 6 FIFO control register */ + __IO uint32 S6CR; /**< Stream 6 control register */ + __IO uint32 S6NDTR; /**< Stream 6 number of data register */ + __IO uint32 S6PAR; /**< Stream 6 peripheral address register */ + __IO uint32 S6M0AR; /**< Stream 6 memory 0 address register */ + __IO uint32 S6M1AR; /**< Stream 6 memory 1 address register */ + __IO uint32 S6FCR; /**< Stream 6 FIFO control register */ /* Stream 7 registers */ - __io uint32 S7CR; /**< Stream 7 control register */ - __io uint32 S7NDTR; /**< Stream 7 number of data register */ - __io uint32 S7PAR; /**< Stream 7 peripheral address register */ - __io uint32 S7M0AR; /**< Stream 7 memory 0 address register */ - __io uint32 S7M1AR; /**< Stream 7 memory 1 address register */ - __io uint32 S7FCR; /**< Stream 7 FIFO control register */ + __IO uint32 S7CR; /**< Stream 7 control register */ + __IO uint32 S7NDTR; /**< Stream 7 number of data register */ + __IO uint32 S7PAR; /**< Stream 7 peripheral address register */ + __IO uint32 S7M0AR; /**< Stream 7 memory 0 address register */ + __IO uint32 S7M1AR; /**< Stream 7 memory 1 address register */ + __IO uint32 S7FCR; /**< Stream 7 FIFO control register */ } dma_reg_map; /** DMA controller 1 register map base pointer */ @@ -124,12 +124,12 @@ typedef struct dma_reg_map { * @see dma_tube_regs() */ typedef struct dma_tube_reg_map { - __io uint32 SCR; /**< Stream configuration register */ - __io uint32 SNDTR; /**< Stream number of data register */ - __io uint32 SPAR; /**< Stream peripheral address register */ - __io uint32 SM0AR; /**< Stream memory 0 address register */ - __io uint32 SM1AR; /**< Stream memory 1 address register */ - __io uint32 SFCR; /**< Stream FIFO control register */ + __IO uint32 SCR; /**< Stream configuration register */ + __IO uint32 SNDTR; /**< Stream number of data register */ + __IO uint32 SPAR; /**< Stream peripheral address register */ + __IO uint32 SM0AR; /**< Stream memory 0 address register */ + __IO uint32 SM1AR; /**< Stream memory 1 address register */ + __IO uint32 SFCR; /**< Stream FIFO control register */ } dma_tube_reg_map; /** DMA1 stream 0 register map base pointer */ @@ -697,7 +697,7 @@ static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube) { /* F2-only; available because of double-buffering. */ void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n, - __io void *address); + __IO void *address); /** * @brief Set memory 0 address. @@ -708,7 +708,7 @@ void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n, * @param addr Address to use as memory 0 */ static inline __always_inline void -dma_set_mem0_addr(dma_dev *dev, dma_tube tube, __io void *addr) { +dma_set_mem0_addr(dma_dev *dev, dma_tube tube, __IO void *addr) { dma_set_mem_n_addr(dev, tube, 0, addr); } @@ -721,13 +721,13 @@ dma_set_mem0_addr(dma_dev *dev, dma_tube tube, __io void *addr) { * @param addr Address to use as memory 1 */ static inline __always_inline void -dma_set_mem1_addr(dma_dev *dev, dma_tube tube, __io void *addr) { +dma_set_mem1_addr(dma_dev *dev, dma_tube tube, __IO void *addr) { dma_set_mem_n_addr(dev, tube, 1, addr); } /* Assume the user means SM0AR in a non-double-buffered configuration. */ static inline __always_inline void -dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *addr) { +dma_set_mem_addr(dma_dev *dev, dma_tube tube, __IO void *addr) { dma_set_mem0_addr(dev, tube, addr); } @@ -791,13 +791,13 @@ static inline __always_inline uint32 _dma_sr_fcr_shift(dma_tube tube) { static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube) { dma_reg_map *regs = dev->regs; - __io uint32 *isr = tube > DMA_S3 ? ®s->HISR : ®s->LISR; + __IO uint32 *isr = tube > DMA_S3 ? ®s->HISR : ®s->LISR; return (*isr >> _dma_sr_fcr_shift(tube)) & 0x3D; } static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) { dma_reg_map *regs = dev->regs; - __io uint32 *ifcr = tube > DMA_S3 ? ®s->HIFCR : ®s->LIFCR; + __IO uint32 *ifcr = tube > DMA_S3 ? ®s->HIFCR : ®s->LIFCR; *ifcr = (0x3D << _dma_sr_fcr_shift(tube)); } diff --git a/STM32F1/system/libmaple/stm32f2/include/series/flash.h b/STM32F1/system/libmaple/stm32f2/include/series/flash.h index a3c3933..a02d4ca 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/flash.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/flash.h @@ -48,12 +48,12 @@ extern "C"{ /** @brief STM32F2 Flash register map type */ typedef struct flash_reg_map { - __io uint32 ACR; /**< Access control register */ - __io uint32 KEYR; /**< Key register */ - __io uint32 OPTKEYR; /**< Option key register */ - __io uint32 SR; /**< Status register */ - __io uint32 CR; /**< Control register */ - __io uint32 OPTCR; /**< Option control register */ + __IO uint32 ACR; /**< Access control register */ + __IO uint32 KEYR; /**< Key register */ + __IO uint32 OPTKEYR; /**< Option key register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 CR; /**< Control register */ + __IO uint32 OPTCR; /**< Option control register */ } flash_reg_map; #define FLASH_BASE ((struct flash_reg_map*)0x40023C00) diff --git a/STM32F1/system/libmaple/stm32f2/include/series/gpio.h b/STM32F1/system/libmaple/stm32f2/include/series/gpio.h index 4d0d98c..13d8366 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/gpio.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/gpio.h @@ -44,16 +44,16 @@ extern "C"{ /** GPIO register map type */ typedef struct gpio_reg_map { - __io uint32 MODER; /**< Mode register */ - __io uint32 OTYPER; /**< Output type register */ - __io uint32 OSPEEDR; /**< Output speed register */ - __io uint32 PUPDR; /**< Pull-up/pull-down register */ - __io uint32 IDR; /**< Input data register */ - __io uint32 ODR; /**< Output data register */ - __io uint32 BSRR; /**< Bit set/reset register */ - __io uint32 LCKR; /**< Configuration lock register */ - __io uint32 AFRL; /**< Alternate function low register */ - __io uint32 AFRH; /**< Alternate function high register */ + __IO uint32 MODER; /**< Mode register */ + __IO uint32 OTYPER; /**< Output type register */ + __IO uint32 OSPEEDR; /**< Output speed register */ + __IO uint32 PUPDR; /**< Pull-up/pull-down register */ + __IO uint32 IDR; /**< Input data register */ + __IO uint32 ODR; /**< Output data register */ + __IO uint32 BSRR; /**< Bit set/reset register */ + __IO uint32 LCKR; /**< Configuration lock register */ + __IO uint32 AFRL; /**< Alternate function low register */ + __IO uint32 AFRH; /**< Alternate function high register */ } gpio_reg_map; /** GPIO port A register map base pointer */ diff --git a/STM32F1/system/libmaple/stm32f2/include/series/rcc.h b/STM32F1/system/libmaple/stm32f2/include/series/rcc.h index 441a5a8..eae4d42 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/rcc.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/rcc.h @@ -44,46 +44,46 @@ extern "C"{ /** STM32F2 RCC register map type */ typedef struct rcc_reg_map { - __io uint32 CR; /**< Clock control register */ - __io uint32 PLLCFGR; /**< PLL configuration register */ - __io uint32 CFGR; /**< Clock configuration register */ - __io uint32 CIR; /**< Clock interrupt register */ - __io uint32 AHB1RSTR; /**< AHB1 peripheral reset register */ - __io uint32 AHB2RSTR; /**< AHB2 peripheral reset register */ - __io uint32 AHB3RSTR; /**< AHB3 peripheral reset register */ + __IO uint32 CR; /**< Clock control register */ + __IO uint32 PLLCFGR; /**< PLL configuration register */ + __IO uint32 CFGR; /**< Clock configuration register */ + __IO uint32 CIR; /**< Clock interrupt register */ + __IO uint32 AHB1RSTR; /**< AHB1 peripheral reset register */ + __IO uint32 AHB2RSTR; /**< AHB2 peripheral reset register */ + __IO uint32 AHB3RSTR; /**< AHB3 peripheral reset register */ const uint32 RESERVED1; /**< Reserved */ - __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ - __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ + __IO uint32 APB1RSTR; /**< APB1 peripheral reset register */ + __IO uint32 APB2RSTR; /**< APB2 peripheral reset register */ const uint32 RESERVED2; /**< Reserved */ const uint32 RESERVED3; /**< Reserved */ - __io uint32 AHB1ENR; /**< AHB1 peripheral clock enable register */ - __io uint32 AHB2ENR; /**< AHB2 peripheral clock enable register */ - __io uint32 AHB3ENR; /**< AHB3 peripheral clock enable register */ + __IO uint32 AHB1ENR; /**< AHB1 peripheral clock enable register */ + __IO uint32 AHB2ENR; /**< AHB2 peripheral clock enable register */ + __IO uint32 AHB3ENR; /**< AHB3 peripheral clock enable register */ const uint32 RESERVED4; /**< Reserved */ - __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ - __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ + __IO uint32 APB1ENR; /**< APB1 peripheral clock enable register */ + __IO uint32 APB2ENR; /**< APB2 peripheral clock enable register */ const uint32 RESERVED5; /**< Reserved */ const uint32 RESERVED6; /**< Reserved */ - __io uint32 AHB1LPENR; /**< AHB1 peripheral clock enable in + __IO uint32 AHB1LPENR; /**< AHB1 peripheral clock enable in low power mode register */ - __io uint32 AHB2LPENR; /**< AHB2 peripheral clock enable in + __IO uint32 AHB2LPENR; /**< AHB2 peripheral clock enable in low power mode register */ - __io uint32 AHB3LPENR; /**< AHB3 peripheral clock enable in + __IO uint32 AHB3LPENR; /**< AHB3 peripheral clock enable in low power mode register */ const uint32 RESERVED7; /**< Reserved */ - __io uint32 APB1LPENR; /**< APB1 peripheral clock enable in + __IO uint32 APB1LPENR; /**< APB1 peripheral clock enable in low power mode register */ - __io uint32 APB2LPENR; /**< APB2 peripheral clock enable in + __IO uint32 APB2LPENR; /**< APB2 peripheral clock enable in low power mode register */ const uint32 RESERVED8; /**< Reserved */ const uint32 RESERVED9; /**< Reserved */ - __io uint32 BDCR; /**< Backup domain control register */ - __io uint32 CSR; /**< Clock control and status register */ + __IO uint32 BDCR; /**< Backup domain control register */ + __IO uint32 CSR; /**< Clock control and status register */ const uint32 RESERVED10; /**< Reserved */ const uint32 RESERVED11; /**< Reserved */ - __io uint32 SSCGR; /**< Spread spectrum clock generation + __IO uint32 SSCGR; /**< Spread spectrum clock generation register */ - __io uint32 PLLI2SCFGR; /**< PLLI2S configuration register */ + __IO uint32 PLLI2SCFGR; /**< PLLI2S configuration register */ } rcc_reg_map; #define RCC_BASE ((struct rcc_reg_map*)0x40023800) diff --git a/STM32F1/system/libmaple/stm32f2/include/series/timer.h b/STM32F1/system/libmaple/stm32f2/include/series/timer.h index a7ac276..94f6547 100644 --- a/STM32F1/system/libmaple/stm32f2/include/series/timer.h +++ b/STM32F1/system/libmaple/stm32f2/include/series/timer.h @@ -47,27 +47,27 @@ * registers. Consult your chip's reference manual for the details. */ typedef struct timer_gen_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SMCR; /**< Slave mode control register */ + __IO uint32 DIER; /**< DMA/Interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ + __IO uint32 CCMR1; /**< Capture/compare mode register 1 */ + __IO uint32 CCMR2; /**< Capture/compare mode register 2 */ + __IO uint32 CCER; /**< Capture/compare enable register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ const uint32 RESERVED1; /**< Reserved */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ + __IO uint32 CCR1; /**< Capture/compare register 1 */ + __IO uint32 CCR2; /**< Capture/compare register 2 */ + __IO uint32 CCR3; /**< Capture/compare register 3 */ + __IO uint32 CCR4; /**< Capture/compare register 4 */ const uint32 RESERVED2; /**< Reserved */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ - __io uint32 OR; /**< Option register. */ + __IO uint32 DCR; /**< DMA control register */ + __IO uint32 DMAR; /**< DMA address for full transfer */ + __IO uint32 OR; /**< Option register. */ } timer_gen_reg_map; struct timer_adv_reg_map; diff --git a/STM32F1/system/libmaple/usb/stm32f1/usb_reg_map.h b/STM32F1/system/libmaple/usb/stm32f1/usb_reg_map.h index d0423fc..cdb7422 100644 --- a/STM32F1/system/libmaple/usb/stm32f1/usb_reg_map.h +++ b/STM32F1/system/libmaple/usb/stm32f1/usb_reg_map.h @@ -42,13 +42,13 @@ /** USB register map type */ typedef struct usb_reg_map { - __io uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */ + __IO uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */ const uint32 RESERVED[8]; /**< Reserved */ - __io uint32 CNTR; /**< Control register */ - __io uint32 ISTR; /**< Interrupt status register */ - __io uint32 FNR; /**< Frame number register */ - __io uint32 DADDR; /**< Device address */ - __io uint32 BTABLE; /**< @brief Buffer table address + __IO uint32 CNTR; /**< Control register */ + __IO uint32 ISTR; /**< Interrupt status register */ + __IO uint32 FNR; /**< Frame number register */ + __IO uint32 DADDR; /**< Device address */ + __IO uint32 BTABLE; /**< @brief Buffer table address * * Address offset within the USB * packet memory area which points @@ -340,7 +340,7 @@ static inline void usb_clear_status_out(uint8 ep) { * * The USB PMA is SRAM shared between USB and CAN. The USB peripheral * accesses this memory directly via the packet buffer interface. */ -#define USB_PMA_BASE ((__io void*)0x40006000) +#define USB_PMA_BASE ((__IO void*)0x40006000) /* * PMA conveniences @@ -367,42 +367,42 @@ union usb_btable_ent; /* Bidirectional endpoint BTABLE entry */ typedef struct usb_btable_bidi { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; + __IO uint16 addr_tx; const uint16 PAD1; + __IO uint16 count_tx; const uint16 PAD2; + __IO uint16 addr_rx; const uint16 PAD3; + __IO uint16 count_rx; const uint16 PAD4; } usb_btable_bidi; /* Unidirectional receive-only endpoint BTABLE entry */ typedef struct usb_btable_uni_rx { - __io uint16 empty1; const uint16 PAD1; - __io uint16 empty2; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; + __IO uint16 empty1; const uint16 PAD1; + __IO uint16 empty2; const uint16 PAD2; + __IO uint16 addr_rx; const uint16 PAD3; + __IO uint16 count_rx; const uint16 PAD4; } usb_btable_uni_rx; /* Unidirectional transmit-only endpoint BTABLE entry */ typedef struct usb_btable_uni_tx { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 empty1; const uint16 PAD3; - __io uint16 empty2; const uint16 PAD4; + __IO uint16 addr_tx; const uint16 PAD1; + __IO uint16 count_tx; const uint16 PAD2; + __IO uint16 empty1; const uint16 PAD3; + __IO uint16 empty2; const uint16 PAD4; } usb_btable_uni_tx; /* Double-buffered transmission endpoint BTABLE entry */ typedef struct usb_btable_dbl_tx { - __io uint16 addr_tx0; const uint16 PAD1; - __io uint16 count_tx0; const uint16 PAD2; - __io uint16 addr_tx1; const uint16 PAD3; - __io uint16 count_tx1; const uint16 PAD4; + __IO uint16 addr_tx0; const uint16 PAD1; + __IO uint16 count_tx0; const uint16 PAD2; + __IO uint16 addr_tx1; const uint16 PAD3; + __IO uint16 count_tx1; const uint16 PAD4; } usb_btable_dbl_tx; /* Double-buffered reception endpoint BTABLE entry */ typedef struct usb_btable_dbl_rx { - __io uint16 addr_rx0; const uint16 PAD1; - __io uint16 count_rx0; const uint16 PAD2; - __io uint16 addr_rx1; const uint16 PAD3; - __io uint16 count_rx1; const uint16 PAD4; + __IO uint16 addr_rx0; const uint16 PAD1; + __IO uint16 count_rx0; const uint16 PAD2; + __IO uint16 addr_rx1; const uint16 PAD3; + __IO uint16 count_rx1; const uint16 PAD4; } usb_btable_dbl_rx; /* TODO isochronous endpoint entries */ diff --git a/STM32F1/system/libmaple/usb/usb_lib/usb_type.h b/STM32F1/system/libmaple/usb/usb_lib/usb_type.h index 34b3bf5..02bd5ef 100644 --- a/STM32F1/system/libmaple/usb/usb_lib/usb_type.h +++ b/STM32F1/system/libmaple/usb/usb_lib/usb_type.h @@ -62,7 +62,7 @@ typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState; -typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; +//typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ diff --git a/STM32F1/variants/STM32VLD/board/board.h b/STM32F1/variants/STM32VLD/board/board.h index ba8d556..be2f19e 100644 --- a/STM32F1/variants/STM32VLD/board/board.h +++ b/STM32F1/variants/STM32VLD/board/board.h @@ -38,7 +38,8 @@ -#define CYCLES_PER_MICROSECOND 24 +//#define CYCLES_PER_MICROSECOND 24 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) //#define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define SYSTICK_RELOAD_VAL 23999 /* takes a cycle to reload */ diff --git a/STM32F1/variants/STM32VLD/wirish/boards.cpp b/STM32F1/variants/STM32VLD/wirish/boards.cpp index 5274e7a..7b7e9a6 100644 --- a/STM32F1/variants/STM32VLD/wirish/boards.cpp +++ b/STM32F1/variants/STM32VLD/wirish/boards.cpp @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/STM32VLD/wirish/syscalls.c b/STM32F1/variants/STM32VLD/wirish/syscalls.c index d42536c..91ed5a1 100644 --- a/STM32F1/variants/STM32VLD/wirish/syscalls.c +++ b/STM32F1/variants/STM32VLD/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_gd32f103c/board/board.h b/STM32F1/variants/generic_gd32f103c/board/board.h index 209bc36..16295a1 100644 --- a/STM32F1/variants/generic_gd32f103c/board/board.h +++ b/STM32F1/variants/generic_gd32f103c/board/board.h @@ -36,7 +36,7 @@ #ifndef _BOARD_GENERIC_STM32F103C_H_ #define _BOARD_GENERIC_STM32F103C_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_NR_USARTS 3 @@ -70,8 +70,8 @@ #define BOARD_JTDO_PIN 19 #define BOARD_NJTRST_PIN 18 -#define BOARD_USB_DISC_DEV GPIOB -#define BOARD_USB_DISC_BIT 10 +#define BOARD_USB_DISC_DEV NULL +#define BOARD_USB_DISC_BIT NULL // Note this needs to match with the PIN_MAP array in board.cpp enum { diff --git a/STM32F1/variants/generic_gd32f103c/wirish/boards.cpp b/STM32F1/variants/generic_gd32f103c/wirish/boards.cpp index fcb85b2..93ae231 100644 --- a/STM32F1/variants/generic_gd32f103c/wirish/boards.cpp +++ b/STM32F1/variants/generic_gd32f103c/wirish/boards.cpp @@ -120,12 +120,12 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/generic_gd32f103c/wirish/boards_setup.cpp b/STM32F1/variants/generic_gd32f103c/wirish/boards_setup.cpp index 3df1fe7..a297de1 100644 --- a/STM32F1/variants/generic_gd32f103c/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_gd32f103c/wirish/boards_setup.cpp @@ -46,6 +46,7 @@ // Additionally the GD32 has a 4 USB PLL divider settings, rather than the 2 settings in the STM32, which allow it to operate on frequencies of 48,72,96 and 120Mhz and still have USB functioning #ifndef BOARD_RCC_PLLMUL +#if !USE_HSI_CLOCK #if F_CPU==120000000 #define BOARD_RCC_PLLMUL RCC_PLLMUL_10 #elif F_CPU==96000000 @@ -53,14 +54,20 @@ #elif F_CPU==72000000 #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 #endif - +#else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 +#endif #endif namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_gd32f103c/wirish/syscalls.c b/STM32F1/variants/generic_gd32f103c/wirish/syscalls.c index d5f2d9f..6558dbd 100644 --- a/STM32F1/variants/generic_gd32f103c/wirish/syscalls.c +++ b/STM32F1/variants/generic_gd32f103c/wirish/syscalls.c @@ -76,15 +76,15 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } @@ -97,7 +97,7 @@ __weak int isatty(int fd) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_stm32f103c/board/board.h b/STM32F1/variants/generic_stm32f103c/board/board.h index d2a4fd6..4736dc9 100644 --- a/STM32F1/variants/generic_stm32f103c/board/board.h +++ b/STM32F1/variants/generic_stm32f103c/board/board.h @@ -36,7 +36,7 @@ #ifndef _BOARD_GENERIC_STM32F103C_H_ #define _BOARD_GENERIC_STM32F103C_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_NR_USARTS 3 @@ -70,8 +70,10 @@ #define BOARD_JTDO_PIN 19 #define BOARD_NJTRST_PIN 18 -#define BOARD_USB_DISC_DEV GPIOB -#define BOARD_USB_DISC_BIT 10 +#define BOARD_USB_DISC_DEV NULL +#define BOARD_USB_DISC_BIT NULL + +#define LED_BUILTIN PC13 // Note this needs to match with the PIN_MAP array in board.cpp enum { diff --git a/STM32F1/variants/generic_stm32f103c/variant.h b/STM32F1/variants/generic_stm32f103c/variant.h index 4a9cfcd..dc4b894 100644 --- a/STM32F1/variants/generic_stm32f103c/variant.h +++ b/STM32F1/variants/generic_stm32f103c/variant.h @@ -19,4 +19,4 @@ static const uint8_t SCK = BOARD_SPI1_SCK_PIN; #define LED_BUILTIN PC13 -#endif /* _VARIANT_ARDUINO_STM32_ */ \ No newline at end of file +#endif /* _VARIANT_ARDUINO_STM32_ */ diff --git a/STM32F1/variants/generic_stm32f103c/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103c/wirish/boards.cpp index 36fcb3e..53f3469 100644 --- a/STM32F1/variants/generic_stm32f103c/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103c/wirish/boards.cpp @@ -120,12 +120,12 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/generic_stm32f103c/wirish/boards_setup.cpp b/STM32F1/variants/generic_stm32f103c/wirish/boards_setup.cpp index 5516282..59e8228 100644 --- a/STM32F1/variants/generic_stm32f103c/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103c/wirish/boards_setup.cpp @@ -48,10 +48,18 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 #endif #endif @@ -59,7 +67,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c index d42536c..91ed5a1 100644 --- a/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_stm32f103r/board.cpp b/STM32F1/variants/generic_stm32f103r/board.cpp index 3e3589c..891e4e9 100644 --- a/STM32F1/variants/generic_stm32f103r/board.cpp +++ b/STM32F1/variants/generic_stm32f103r/board.cpp @@ -78,7 +78,6 @@ extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { uint8 gpio_bit; Pin's GPIO port bit. uint8 timer_channel; Timer channel, or 0 if none. uint8 adc_channel; Pin ADC channel, or ADCx if none. - uint8 pinMode; mode specific by pinMode call (Roger Clark added to optimize compatibility with Arduino API */ {&gpioa, &timer2, &adc1, 0, 1, 0}, /* PA0 */ diff --git a/STM32F1/variants/generic_stm32f103r/board/board.h b/STM32F1/variants/generic_stm32f103r/board/board.h index 0719afa..925c882 100644 --- a/STM32F1/variants/generic_stm32f103r/board/board.h +++ b/STM32F1/variants/generic_stm32f103r/board/board.h @@ -102,6 +102,16 @@ #define BOARD_USB_DISC_DEV GPIOC #define BOARD_USB_DISC_BIT 12 +/* + * SDIO Pins + */ +#define BOARD_SDIO_D0 PC8 +#define BOARD_SDIO_D1 PC9 +#define BOARD_SDIO_D2 PC10 +#define BOARD_SDIO_D3 PC11 +#define BOARD_SDIO_CLK PC12 +#define BOARD_SDIO_CMD PD2 + /* Pin aliases: these give the GPIO port/bit for each pin as an * enum. These are optional, but recommended. They make it easier to * write code using low-level GPIO functionality. */ diff --git a/STM32F1/variants/generic_stm32f103r/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103r/wirish/boards.cpp index fcb85b2..93ae231 100644 --- a/STM32F1/variants/generic_stm32f103r/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103r/wirish/boards.cpp @@ -120,12 +120,12 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/generic_stm32f103r/wirish/boards_setup.cpp b/STM32F1/variants/generic_stm32f103r/wirish/boards_setup.cpp index d7774f7..c804d7f 100644 --- a/STM32F1/variants/generic_stm32f103r/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103r/wirish/boards_setup.cpp @@ -48,10 +48,18 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 #endif #endif @@ -59,7 +67,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_stm32f103r8/board/board.h b/STM32F1/variants/generic_stm32f103r8/board/board.h index 5f6855d..36c2241 100644 --- a/STM32F1/variants/generic_stm32f103r8/board/board.h +++ b/STM32F1/variants/generic_stm32f103r8/board/board.h @@ -36,7 +36,7 @@ #ifndef _BOARD_GENERIC_STM32F103R8_H_ #define _BOARD_GENERIC_STM32F103R8_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_NR_USARTS 3 @@ -70,8 +70,8 @@ #define BOARD_JTDO_PIN 19 #define BOARD_NJTRST_PIN 18 -#define BOARD_USB_DISC_DEV GPIOB -#define BOARD_USB_DISC_BIT 10 +#define BOARD_USB_DISC_DEV NULL +#define BOARD_USB_DISC_BIT NULL // Note this needs to match with the PIN_MAP array in board.cpp enum { diff --git a/STM32F1/variants/generic_stm32f103r8/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103r8/wirish/boards.cpp index 5274e7a..8806343 100644 --- a/STM32F1/variants/generic_stm32f103r8/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103r8/wirish/boards.cpp @@ -120,12 +120,12 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/generic_stm32f103r8/wirish/boards_setup.cpp b/STM32F1/variants/generic_stm32f103r8/wirish/boards_setup.cpp index 7c93977..9e9c3c0 100644 --- a/STM32F1/variants/generic_stm32f103r8/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103r8/wirish/boards_setup.cpp @@ -48,10 +48,18 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 #endif #endif @@ -59,7 +67,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_stm32f103r8/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103r8/wirish/syscalls.c index d42536c..91ed5a1 100644 --- a/STM32F1/variants/generic_stm32f103r8/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103r8/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_stm32f103t/board/board.h b/STM32F1/variants/generic_stm32f103t/board/board.h index 5454958..9b261f6 100644 --- a/STM32F1/variants/generic_stm32f103t/board/board.h +++ b/STM32F1/variants/generic_stm32f103t/board/board.h @@ -36,7 +36,7 @@ #ifndef _BOARD_GENERIC_STM32F103T_H_ #define _BOARD_GENERIC_STM32F103T_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_NR_USARTS 2 diff --git a/STM32F1/variants/generic_stm32f103t/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103t/wirish/boards.cpp index 0c018e8..8806343 100644 --- a/STM32F1/variants/generic_stm32f103t/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103t/wirish/boards.cpp @@ -120,12 +120,12 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; @@ -179,7 +175,7 @@ nvic_init((uint32)VECT_TAB_ADDR, 0); */ } -static void adc_default_config(const adc_dev *dev) { +static void adc_default_config(adc_dev *dev) { adc_enable_single_swstart(dev); adc_set_sample_rate(dev, wirish::priv::w_adc_smp); } diff --git a/STM32F1/variants/generic_stm32f103t/wirish/boards_setup.cpp b/STM32F1/variants/generic_stm32f103t/wirish/boards_setup.cpp index 5516282..59e8228 100644 --- a/STM32F1/variants/generic_stm32f103t/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103t/wirish/boards_setup.cpp @@ -48,10 +48,18 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 #endif #endif @@ -59,7 +67,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_stm32f103t/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103t/wirish/syscalls.c index d42536c..91ed5a1 100644 --- a/STM32F1/variants/generic_stm32f103t/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103t/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_stm32f103v/board.cpp b/STM32F1/variants/generic_stm32f103v/board.cpp index 9c13772..d5596a2 100644 --- a/STM32F1/variants/generic_stm32f103v/board.cpp +++ b/STM32F1/variants/generic_stm32f103v/board.cpp @@ -98,7 +98,7 @@ extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { {&gpiob, &timer3, &adc1, 0, 3, 8}, /* PB0 */ {&gpiob, &timer3, &adc1, 1, 4, 9}, /* PB1 */ - /* NOTE PB2 is not included as its Boot 1 */ + {&gpiob, NULL, NULL, 2, 0, ADCx}, /* PB2 */ // Boot1 pin. It affects boot mode (flash, RAM, ROM) {&gpiob, NULL, NULL, 3, 0, ADCx}, /* PB3 */ //JTDO, SPI3_SCK / I2S3_CK/ {&gpiob, NULL, NULL, 4, 0, ADCx}, /* PB4 */ //NJTRST, SPI3_MISO {&gpiob, NULL, NULL, 5, 0, ADCx}, /* PB5 */ //I2C1_SMBA/ SPI3_MOSI @@ -196,4 +196,4 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { DEFINE_HWSERIAL(Serial2, 3); DEFINE_HWSERIAL_UART(Serial3, 4); DEFINE_HWSERIAL_UART(Serial4, 5); -#endif \ No newline at end of file +#endif diff --git a/STM32F1/variants/generic_stm32f103v/board/board.h b/STM32F1/variants/generic_stm32f103v/board/board.h index 210dbf8..e4bd089 100644 --- a/STM32F1/variants/generic_stm32f103v/board/board.h +++ b/STM32F1/variants/generic_stm32f103v/board/board.h @@ -38,7 +38,7 @@ /* A few of these values will seem strange given that it's a * high-density board. */ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_BUTTON_PIN PC0 @@ -90,8 +90,9 @@ #define BOARD_SPI3_MOSI_PIN PB5 -/* GPIO A to E = 5 * 16 - BOOT1 not used = 79*/ -#define BOARD_NR_GPIO_PINS 79 +/* GPIO A to E = 5 * 16 = 80*/ +/* value is now 80 as boo1 was added via PR to the pinmap but this value was not increased*/ +#define BOARD_NR_GPIO_PINS 80 /* Note: NOT 19. The missing one is D38 a.k.a. BOARD_BUTTON_PIN, which * isn't broken out to a header and is thus unusable for PWM. */ #define BOARD_NR_PWM_PINS 19 @@ -109,15 +110,25 @@ #define BOARD_USB_DISC_DEV GPIOC #define BOARD_USB_DISC_BIT 12 +/* + * SDIO Pins + */ +#define BOARD_SDIO_D0 PC8 +#define BOARD_SDIO_D1 PC9 +#define BOARD_SDIO_D2 PC10 +#define BOARD_SDIO_D3 PC11 +#define BOARD_SDIO_CLK PC12 +#define BOARD_SDIO_CMD PD2 + /* Pin aliases: these give the GPIO port/bit for each pin as an * enum. These are optional, but recommended. They make it easier to * write code using low-level GPIO functionality. */ enum { PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7,PA8,PA9,PA10,PA11,PA12,PA13,PA14,PA15, -PB0,PB1,PB3,PB4,PB5,PB6,PB7,PB8,PB9,PB10,PB11,PB12,PB13,PB14,PB15, +PB0,PB1,PB2,PB3,PB4,PB5,PB6,PB7,PB8,PB9,PB10,PB11,PB12,PB13,PB14,PB15, PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15, PD0,PD1,PD2,PD3,PD4,PD5,PD6,PD7,PD8,PD9,PD10,PD11,PD12,PD13,PD14,PD15, PE0,PE1,PE2,PE3,PE4,PE5,PE6,PE7,PE8,PE9,PE10,PE11,PE12,PE13,PE14,PE15, -};/* Note PB2 is skipped as this is Boot1 and is not going to be much use as its likely to be pulled permanently low */ +}; #endif diff --git a/STM32F1/variants/generic_stm32f103v/ld/stm32f103vc.ld b/STM32F1/variants/generic_stm32f103v/ld/stm32f103vc.ld index 7efca5d..6079807 100644 --- a/STM32F1/variants/generic_stm32f103v/ld/stm32f103vc.ld +++ b/STM32F1/variants/generic_stm32f103v/ld/stm32f103vc.ld @@ -16,7 +16,7 @@ */ MEMORY { - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K } diff --git a/STM32F1/variants/generic_stm32f103v/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103v/wirish/boards.cpp index 254666f..a2867b8 100644 --- a/STM32F1/variants/generic_stm32f103v/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103v/wirish/boards.cpp @@ -120,16 +120,22 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); +#ifdef XTAL16M + // 16MHz crystal (HSE) + // in this case we additionally set the Bit 17 (PLLXTPRE=1) => then HSE clock is divided by 2 before PLL entry + RCC_BASE->CFGR |= RCC_CFGR_PLLXTPRE; +#endif + // Enable the PLL, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_PLL); while(!rcc_is_clk_ready(RCC_CLK_PLL)) @@ -147,11 +153,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/generic_stm32f103v/wirish/boards_setup.cpp b/STM32F1/variants/generic_stm32f103v/wirish/boards_setup.cpp index 1f23679..5ea718b 100644 --- a/STM32F1/variants/generic_stm32f103v/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103v/wirish/boards_setup.cpp @@ -48,10 +48,18 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 #endif #endif @@ -59,7 +67,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_stm32f103v/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103v/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/generic_stm32f103v/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103v/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_stm32f103vb/board.cpp b/STM32F1/variants/generic_stm32f103vb/board.cpp new file mode 100644 index 0000000..e0b03b8 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/board.cpp @@ -0,0 +1,190 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ +#warning "vb" +/** + * @file wirish/boards/maple_mini/board.cpp + * @author Marti Bolivar + * @brief Maple Mini board file. + */ + +#include + +#include +#include + +/* Roger Clark. Added next to includes for changes to Serial */ +#include +#include + +#include +#include + +/* Since we want the Serial Wire/JTAG pins as GPIOs, disable both SW + * and JTAG debug support, unless configured otherwise. */ +void boardInit(void) { +#ifndef CONFIG_MAPLE_MINI_NO_DISABLE_DEBUG + disableDebugPorts(); +#endif +} + +// Note. See the enum of pin names in board.h + +extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { + + + {&gpioa, &timer2, &adc1, 0, 1, 0}, /* PA0 */ + {&gpioa, &timer2, &adc1, 1, 2, 1}, /* PA1 */ + {&gpioa, &timer2, &adc1, 2, 3, 2}, /* PA2 */ + {&gpioa, &timer2, &adc1, 3, 4, 3}, /* PA3 */ + {&gpioa, NULL, &adc1, 4, 0, 4}, /* PA4 */ + {&gpioa, NULL, &adc1, 5, 0, 5}, /* PA5 */ + {&gpioa, &timer3, &adc1, 6, 1, 6}, /* PA6 */ + {&gpioa, &timer3, &adc1, 7, 2, 7}, /* PA7 */ + {&gpioa, &timer1, NULL, 8, 1, ADCx}, /* PA8 */ + {&gpioa, &timer1, NULL, 9, 2, ADCx}, /* PA9 */ + {&gpioa, &timer1, NULL, 10, 3, ADCx}, /* PA10 */ + {&gpioa, &timer1, NULL, 11, 4, ADCx}, /* PA11 */ + {&gpioa, NULL, NULL, 12, 0, ADCx}, /* PA12 */ + {&gpioa, NULL, NULL, 13, 0, ADCx}, /* PA13 */ + {&gpioa, NULL, NULL, 14, 0, ADCx}, /* PA14 */ + {&gpioa, NULL, NULL, 15, 0, ADCx}, /* PA15 */ + + {&gpiob, &timer3, &adc1, 0, 3, 8}, /* PB0 */ + {&gpiob, &timer3, &adc1, 1, 4, 9}, /* PB1 */ + {&gpiob, NULL, NULL, 2, 0, ADCx}, /* PB2 */ + {&gpiob, NULL, NULL, 3, 0, ADCx}, /* PB3 */ + {&gpiob, NULL, NULL, 4, 0, ADCx}, /* PB4 */ + {&gpiob, NULL, NULL, 5, 0, ADCx}, /* PB5 */ + {&gpiob, &timer4, NULL, 6, 1, ADCx}, /* PB6 */ + {&gpiob, &timer4, NULL, 7, 2, ADCx}, /* PB7 */ + {&gpiob, &timer4, NULL, 8, 3, ADCx}, /* PB8 */ + {&gpiob, &timer4, NULL, 9, 4, ADCx}, /* PB9 */ + {&gpiob, NULL, NULL, 10, 0, ADCx}, /* PB10 */ + {&gpiob, NULL, NULL, 11, 0, ADCx}, /* PB11 */ + {&gpiob, NULL, NULL, 12, 0, ADCx}, /* PB12 */ + {&gpiob, NULL, NULL, 13, 0, ADCx}, /* PB13 */ + {&gpiob, NULL, NULL, 14, 0, ADCx}, /* PB14 */ + {&gpiob, NULL, NULL, 15, 0, ADCx}, /* PB15 */ + + {&gpioc, NULL, &adc1, 0, 0, 10}, /* PC0 */ + {&gpioc, NULL, &adc1, 1, 0, 11}, /* PC1 */ + {&gpioc, NULL, &adc1, 2, 0, 12}, /* PC2 */ + {&gpioc, NULL, &adc1, 3, 0, 13}, /* PC3 */ + {&gpioc, NULL, &adc1, 4, 0, 14}, /* PC4 */ + {&gpioc, NULL, &adc1, 5, 0, 15}, /* PC5 */ + + {&gpioc, NULL, NULL, 6, 0, ADCx}, /* PC6 */ + {&gpioc, NULL, NULL, 7, 0, ADCx}, /* PC7 */ + {&gpioc, NULL, NULL, 8, 0, ADCx}, /* PC8 */ + {&gpioc, NULL, NULL, 9, 0, ADCx}, /* PC9 */ + + {&gpioc, NULL, NULL, 10, 0, ADCx}, /* PC10 */ + {&gpioc, NULL, NULL, 11, 0, ADCx}, /* PC11 */ + {&gpioc, NULL, NULL, 12, 0, ADCx}, /* PC12 */ + {&gpioc, NULL, NULL, 13, 0, ADCx}, /* PC13 */ + {&gpioc, NULL, NULL, 14, 0, ADCx}, /* PC14 */ + {&gpioc, NULL, NULL, 15, 0, ADCx}, /* PC15 */ + +/* the VB is similar to the RB but exposes more GPIO as follows */ + {&gpiod, NULL, NULL, 0, 0, ADCx} , /* PD0 N */ + {&gpiod, NULL, NULL, 1, 0, ADCx} , /* PD1 */ + {&gpiod, NULL, NULL, 2, 0, ADCx} , /* PD2 TIM3_ETR */ + {&gpiod, NULL, NULL, 3, 0, ADCx} , /* PD3 */ + {&gpiod, NULL, NULL, 4, 0, ADCx} , /* PD4 */ + {&gpiod, NULL, NULL, 5, 0, ADCx} , /* PD5 */ + {&gpiod, NULL, NULL, 6, 0, ADCx} , /* PD6 */ + {&gpiod, NULL, NULL, 7, 0, ADCx} , /* PD7 */ + {&gpiod, NULL, NULL, 8, 0, ADCx} , /* PD8 */ + {&gpiod, NULL, NULL, 9, 0, ADCx} , /* PD9 */ + {&gpiod, NULL, NULL, 10, 0, ADCx} , /* PD10 */ + {&gpiod, NULL, NULL, 11, 0, ADCx} , /* PD11 */ + {&gpiod, NULL, NULL, 12, 0, ADCx} , /* PD12 */ + {&gpiod, NULL, NULL, 13, 0, ADCx} , /* PD13 */ + {&gpiod, NULL, NULL, 14, 0, ADCx} , /* PD14 */ + {&gpiod, NULL, NULL, 15, 0, ADCx} , /* PD15 */ + + {&gpioe, NULL, NULL, 0, 0, ADCx} , /* PE0 TIM4_ETR / FSMC_NBL0 */ + {&gpioe, NULL, NULL, 1, 0, ADCx} , /* PE1 FSMC_NBL1 */ + {&gpioe, NULL, NULL, 2, 0, ADCx} , /* PE2 TRACECK */ + {&gpioe, NULL, NULL, 3, 0, ADCx} , /* PE3 TRACED0 */ + {&gpioe, NULL, NULL, 4, 0, ADCx} , /* PE4 TRACED1 */ + {&gpioe, NULL, NULL, 5, 0, ADCx} , /* PE5 TRACED2 */ + {&gpioe, NULL, NULL, 6, 0, ADCx} , /* PE6 TRACED3 */ + {&gpioe, NULL, NULL, 7, 0, ADCx} , /* PE7 */ + {&gpioe, NULL, NULL, 8, 0, ADCx} , /* PE8 */ + {&gpioe, NULL, NULL, 9, 0, ADCx} , /* PE9 */ + {&gpioe, NULL, NULL, 10, 0, ADCx} , /* PE10 */ + {&gpioe, NULL, NULL, 11, 0, ADCx} , /* PE11 */ + {&gpioe, NULL, NULL, 12, 0, ADCx} , /* PE12 */ + {&gpioe, NULL, NULL, 13, 0, ADCx} , /* PE13 */ + {&gpioe, NULL, NULL, 14, 0, ADCx} , /* PE14 */ + {&gpioe, NULL, NULL, 15, 0, ADCx} , /* PE15 */ + +}; + +extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { + PB0, PA7, PA6, PA3, PA2, PA1, PA0, PB7, PB6, PA10, PA9, PA8, PC6, PC7, PC8, PC9 +}; + +extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = { + PB0, PA7, PA6 , PA5 , PA4 , PA3 , PA2 , PA1 , PA0 , PC0, PC1, PC2, PC3, PC4, PC5 +}; + +// Note. These defines are not really used by generic boards. They are for Maple Serial USB +#define USB_DP PA12 +#define USB_DM PA11 + +// NOte. These definitions are not really used for generic boards, they only relate to boards modified to behave like Maple boards +extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { + USB_DP, USB_DM +}; + + +/* + * Roger Clark + * + * 2015/05/28 + * + * Moved definitions for Hardware Serial devices from HardwareSerial.cpp so that each board can define which Arduino "Serial" instance + * Maps to which hardware serial port on the microprocessor + */ + +#ifdef SERIAL_USB + DEFINE_HWSERIAL(Serial1, 1); + + DEFINE_HWSERIAL(Serial2, 2); + + DEFINE_HWSERIAL(Serial3, 3); + +#else + DEFINE_HWSERIAL(Serial, 1); + + DEFINE_HWSERIAL(Serial1, 2); + + DEFINE_HWSERIAL(Serial2, 3); + + +#endif diff --git a/STM32F1/variants/generic_stm32f103vb/board/board.h b/STM32F1/variants/generic_stm32f103vb/board/board.h new file mode 100644 index 0000000..1271bb0 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/board/board.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/boards/maple_mini/include/board/board.h + * @author Marti Bolivar + * @brief Maple Mini board header. + * + * See wirish/boards/maple/include/board/board.h for more information + * on these definitions. + */ +#ifndef _BOARD_GENERIC_STM32F103VB_H_ +#define _BOARD_GENERIC_STM32F103VB_H_ + +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) +#define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ + +#define BOARD_NR_USARTS 3 +#define BOARD_USART1_TX_PIN PA9 +#define BOARD_USART1_RX_PIN PA10 +#define BOARD_USART2_TX_PIN PA2 +#define BOARD_USART2_RX_PIN PA3 +#define BOARD_USART3_TX_PIN PB10 +#define BOARD_USART3_RX_PIN PB11 + +#define BOARD_NR_SPI 2 +#define BOARD_SPI1_NSS_PIN PA4 +#define BOARD_SPI1_MOSI_PIN PA7 +#define BOARD_SPI1_MISO_PIN PA6 +#define BOARD_SPI1_SCK_PIN PA5 + +#define BOARD_SPI2_NSS_PIN PB12 +#define BOARD_SPI2_MOSI_PIN PB15 +#define BOARD_SPI2_MISO_PIN PB14 +#define BOARD_SPI2_SCK_PIN PB13 + +#define BOARD_NR_GPIO_PINS 80 +#define BOARD_NR_PWM_PINS 16 +#define BOARD_NR_ADC_PINS 15 +#define BOARD_NR_USED_PINS 4 + + +#define BOARD_JTMS_SWDIO_PIN 22 +#define BOARD_JTCK_SWCLK_PIN 21 +#define BOARD_JTDI_PIN 20 +#define BOARD_JTDO_PIN 19 +#define BOARD_NJTRST_PIN 18 + +#define BOARD_USB_DISC_DEV NULL +#define BOARD_USB_DISC_BIT NULL + +// Note this needs to match with the PIN_MAP array in board.cpp +enum { + PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15, + PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, + PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15, + PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15, + PE0, PE1, PE2, PE3, PE4, PE5, PE6, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15 +}; + +#endif diff --git a/STM32F1/variants/generic_stm32f103vb/ld/bootloader.ld b/STM32F1/variants/generic_stm32f103vb/ld/bootloader.ld new file mode 100644 index 0000000..348b19c --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/bootloader.ld @@ -0,0 +1,18 @@ +/* + * Linker script for Generic STM32F103RE boards, using the generic bootloader (which takes the lower 8k of memory) + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K +} + + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/STM32F1/variants/generic_stm32f103vb/ld/bootloader_20.ld b/STM32F1/variants/generic_stm32f103vb/ld/bootloader_20.ld new file mode 100644 index 0000000..4de3a08 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/bootloader_20.ld @@ -0,0 +1,30 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K +} + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/STM32F1/variants/generic_stm32f103vb/ld/common.inc b/STM32F1/variants/generic_stm32f103vb/ld/common.inc new file mode 100644 index 0000000..e086a58 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/common.inc @@ -0,0 +1,220 @@ +/* + * Linker script for libmaple. + * + * Original author "lanchon" from ST forums, with modifications by LeafLabs. + */ + +OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") + +/* + * Configure other libraries we want in the link. + * + * libgcc, libc, and libm are common across supported toolchains. + * However, some toolchains require additional archives which aren't + * present everywhere (e.g. ARM's gcc-arm-embedded releases). + * + * To hack around this, we let the build system specify additional + * archives by putting the right extra_libs.inc (in a directory under + * toolchains/) in our search path. + */ +GROUP(libgcc.a libc.a libm.a) +INCLUDE extra_libs.inc + +/* + * These force the linker to search for vector table symbols. + * + * These symbols vary by STM32 family (and also within families). + * It's up to the build system to configure the link's search path + * properly for the target MCU. + */ +INCLUDE vector_symbols.inc + +/* STM32 vector table. */ +EXTERN(__stm32_vector_table) + +/* C runtime initialization function. */ +EXTERN(start_c) + +/* main entry point */ +EXTERN(main) + +/* Initial stack pointer value. */ +EXTERN(__msp_init) +PROVIDE(__msp_init = ORIGIN(ram) + LENGTH(ram)); + +/* Reset vector and chip reset entry point */ +EXTERN(__start__) +ENTRY(__start__) +PROVIDE(__exc_reset = __start__); + +/* Heap boundaries, for libmaple */ +EXTERN(_lm_heap_start); +EXTERN(_lm_heap_end); + +SECTIONS +{ + .text : + { + __text_start__ = .; + /* + * STM32 vector table. Leave this here. Yes, really. + */ + *(.stm32.interrupt_vector) + + /* + * Program code and vague linking + */ + *(.text .text.* .gnu.linkonce.t.*) + *(.plt) + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) + + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.gcc_except_table) + *(.eh_frame_hdr) + *(.eh_frame) + + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(0x4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > REGION_TEXT + + /* + * End of text + */ + .text.align : + { + . = ALIGN(8); + __text_end__ = .; + } > REGION_TEXT + + /* + * .ARM.exidx exception unwinding; mandated by ARM's C++ ABI + */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > REGION_RODATA + __exidx_end = .; + + /* + * .data + */ + .data : + { + __data_start__ = .; + LONG(0) + . = ALIGN(8); + + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + + . = ALIGN(8); + __data_end__ = .; + } > REGION_DATA AT> REGION_RODATA + + /* + * Read-only data + */ + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + /* .USER_FLASH: We allow users to allocate into Flash here */ + *(.USER_FLASH) + /* ROM image configuration; for C startup */ + . = ALIGN(4); + _lm_rom_img_cfgp = .; + LONG(LOADADDR(.data)); + /* + * Heap: Linker scripts may choose a custom heap by overriding + * _lm_heap_start and _lm_heap_end. Otherwise, the heap is in + * internal SRAM, beginning after .bss, and growing towards + * the stack. + * + * I'm shoving these here naively; there's probably a cleaner way + * to go about this. [mbolivar] + */ + _lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : _end; + _lm_heap_end = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init; + } > REGION_RODATA + + /* + * .bss + */ + .bss : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end__ = .; + _end = __bss_end__; + } > REGION_BSS + + /* + * Debugging sections + */ + .stab 0 (NOLOAD) : { *(.stab) } + .stabstr 0 (NOLOAD) : { *(.stabstr) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/STM32F3/variants/discovery_f3/ld/extra_libs.inc b/STM32F1/variants/generic_stm32f103vb/ld/extra_libs.inc similarity index 100% rename from STM32F3/variants/discovery_f3/ld/extra_libs.inc rename to STM32F1/variants/generic_stm32f103vb/ld/extra_libs.inc diff --git a/STM32F3/variants/discovery_f3/ld/flash.ld b/STM32F1/variants/generic_stm32f103vb/ld/flash.ld similarity index 96% rename from STM32F3/variants/discovery_f3/ld/flash.ld rename to STM32F1/variants/generic_stm32f103vb/ld/flash.ld index 2fa9035..9e250cd 100644 --- a/STM32F3/variants/discovery_f3/ld/flash.ld +++ b/STM32F1/variants/generic_stm32f103vb/ld/flash.ld @@ -14,7 +14,6 @@ * use this file to use any of libmaple's memory-related hooks (like * where the heap should live). */ - INCLUDE mem-flash.inc /* Provide memory region aliases for common.inc */ @@ -22,7 +21,6 @@ REGION_ALIAS("REGION_TEXT", rom); REGION_ALIAS("REGION_DATA", ram); REGION_ALIAS("REGION_BSS", ram); REGION_ALIAS("REGION_RODATA", rom); -REGION_ALIAS("REGION_CCM", ccm); /* Let common.inc handle the real work. */ INCLUDE common.inc diff --git a/STM32F3/variants/discovery_f3/ld/jtag.ld b/STM32F1/variants/generic_stm32f103vb/ld/jtag.ld similarity index 97% rename from STM32F3/variants/discovery_f3/ld/jtag.ld rename to STM32F1/variants/generic_stm32f103vb/ld/jtag.ld index cf08b20..0612f95 100644 --- a/STM32F3/variants/discovery_f3/ld/jtag.ld +++ b/STM32F1/variants/generic_stm32f103vb/ld/jtag.ld @@ -19,7 +19,6 @@ * use this file to use any of libmaple's memory-related hooks (like * where the heap should live). */ - INCLUDE mem-jtag.inc /* Provide memory region aliases for common.inc */ @@ -27,7 +26,6 @@ REGION_ALIAS("REGION_TEXT", rom); REGION_ALIAS("REGION_DATA", ram); REGION_ALIAS("REGION_BSS", ram); REGION_ALIAS("REGION_RODATA", rom); -REGION_ALIAS("REGION_CCM", ccm); /* Let common.inc handle the real work. */ INCLUDE common.inc diff --git a/STM32F1/variants/generic_stm32f103vb/ld/mem-flash.inc b/STM32F1/variants/generic_stm32f103vb/ld/mem-flash.inc new file mode 100644 index 0000000..a9091ca --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 108K +} diff --git a/STM32F1/variants/generic_stm32f103vb/ld/mem-jtag.inc b/STM32F1/variants/generic_stm32f103vb/ld/mem-jtag.inc new file mode 100644 index 0000000..20fbec0 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/STM32F1/variants/generic_stm32f103vb/ld/mem-ram.inc b/STM32F1/variants/generic_stm32f103vb/ld/mem-ram.inc new file mode 100644 index 0000000..f02453b --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} diff --git a/STM32F3/variants/discovery_f3/ld/ram.ld b/STM32F1/variants/generic_stm32f103vb/ld/ram.ld similarity index 96% rename from STM32F3/variants/discovery_f3/ld/ram.ld rename to STM32F1/variants/generic_stm32f103vb/ld/ram.ld index 0484423..34b468e 100644 --- a/STM32F3/variants/discovery_f3/ld/ram.ld +++ b/STM32F1/variants/generic_stm32f103vb/ld/ram.ld @@ -13,7 +13,6 @@ * use this file to use any of libmaple's memory-related hooks (like * where the heap should live). */ - INCLUDE mem-ram.inc /* Provide memory region aliases for common.inc */ @@ -21,7 +20,6 @@ REGION_ALIAS("REGION_TEXT", ram); REGION_ALIAS("REGION_DATA", ram); REGION_ALIAS("REGION_BSS", ram); REGION_ALIAS("REGION_RODATA", ram); -REGION_ALIAS("REGION_CCM", ccm); /* Let common.inc handle the real work. */ INCLUDE common.inc diff --git a/STM32F1/variants/generic_stm32f103vb/ld/stm32f103vb.ld b/STM32F1/variants/generic_stm32f103vb/ld/stm32f103vb.ld new file mode 100644 index 0000000..814d508 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/stm32f103vb.ld @@ -0,0 +1,30 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/STM32F1/variants/generic_stm32f103vb/ld/stm32f103veDFU.ld b/STM32F1/variants/generic_stm32f103vb/ld/stm32f103veDFU.ld new file mode 100644 index 0000000..5782fb9 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/stm32f103veDFU.ld @@ -0,0 +1,30 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + rom (rx) : ORIGIN = 0x08002000, LENGTH = 504K +} + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/STM32F1/variants/generic_stm32f103vb/ld/vector_symbols.inc b/STM32F1/variants/generic_stm32f103vb/ld/vector_symbols.inc new file mode 100644 index 0000000..f8519bb --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/ld/vector_symbols.inc @@ -0,0 +1,78 @@ +EXTERN(__msp_init) +EXTERN(__exc_reset) +EXTERN(__exc_nmi) +EXTERN(__exc_hardfault) +EXTERN(__exc_memmanage) +EXTERN(__exc_busfault) +EXTERN(__exc_usagefault) +EXTERN(__stm32reservedexception7) +EXTERN(__stm32reservedexception8) +EXTERN(__stm32reservedexception9) +EXTERN(__stm32reservedexception10) +EXTERN(__exc_svc) +EXTERN(__exc_debug_monitor) +EXTERN(__stm32reservedexception13) +EXTERN(__exc_pendsv) +EXTERN(__exc_systick) + +EXTERN(__irq_wwdg) +EXTERN(__irq_pvd) +EXTERN(__irq_tamper) +EXTERN(__irq_rtc) +EXTERN(__irq_flash) +EXTERN(__irq_rcc) +EXTERN(__irq_exti0) +EXTERN(__irq_exti1) +EXTERN(__irq_exti2) +EXTERN(__irq_exti3) +EXTERN(__irq_exti4) +EXTERN(__irq_dma1_channel1) +EXTERN(__irq_dma1_channel2) +EXTERN(__irq_dma1_channel3) +EXTERN(__irq_dma1_channel4) +EXTERN(__irq_dma1_channel5) +EXTERN(__irq_dma1_channel6) +EXTERN(__irq_dma1_channel7) +EXTERN(__irq_adc) +EXTERN(__irq_usb_hp_can_tx) +EXTERN(__irq_usb_lp_can_rx0) +EXTERN(__irq_can_rx1) +EXTERN(__irq_can_sce) +EXTERN(__irq_exti9_5) +EXTERN(__irq_tim1_brk) +EXTERN(__irq_tim1_up) +EXTERN(__irq_tim1_trg_com) +EXTERN(__irq_tim1_cc) +EXTERN(__irq_tim2) +EXTERN(__irq_tim3) +EXTERN(__irq_tim4) +EXTERN(__irq_i2c1_ev) +EXTERN(__irq_i2c1_er) +EXTERN(__irq_i2c2_ev) +EXTERN(__irq_i2c2_er) +EXTERN(__irq_spi1) +EXTERN(__irq_spi2) +EXTERN(__irq_usart1) +EXTERN(__irq_usart2) +EXTERN(__irq_usart3) +EXTERN(__irq_exti15_10) +EXTERN(__irq_rtcalarm) +EXTERN(__irq_usbwakeup) + +EXTERN(__irq_tim8_brk) +EXTERN(__irq_tim8_up) +EXTERN(__irq_tim8_trg_com) +EXTERN(__irq_tim8_cc) +EXTERN(__irq_adc3) +EXTERN(__irq_fsmc) +EXTERN(__irq_sdio) +EXTERN(__irq_tim5) +EXTERN(__irq_spi3) +EXTERN(__irq_uart4) +EXTERN(__irq_uart5) +EXTERN(__irq_tim6) +EXTERN(__irq_tim7) +EXTERN(__irq_dma2_channel1) +EXTERN(__irq_dma2_channel2) +EXTERN(__irq_dma2_channel3) +EXTERN(__irq_dma2_channel4_5) diff --git a/STM32F1/variants/generic_stm32f103vb/pins_arduino.h b/STM32F1/variants/generic_stm32f103vb/pins_arduino.h new file mode 100644 index 0000000..3052f2e --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/pins_arduino.h @@ -0,0 +1,6 @@ + + + + +// API compatibility +#include "variant.h" \ No newline at end of file diff --git a/STM32F1/variants/generic_stm32f103vb/variant.h b/STM32F1/variants/generic_stm32f103vb/variant.h new file mode 100644 index 0000000..8a88623 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103vb/variant.h @@ -0,0 +1,20 @@ +#ifndef _VARIANT_ARDUINO_STM32_ +#define _VARIANT_ARDUINO_STM32_ + +#define digitalPinToPort(P) ( PIN_MAP[P].gpio_device ) +#define digitalPinToBitMask(P) ( BIT(PIN_MAP[P].gpio_bit) ) +#define portOutputRegister(port) ( &(port->regs->ODR) ) +#define portInputRegister(port) ( &(port->regs->IDR) ) + +#define portSetRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BSRR) ) +#define portClearRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BRR) ) + +#define portConfigRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->CRL) ) + +static const uint8_t SS = BOARD_SPI1_NSS_PIN; +static const uint8_t SS1 = BOARD_SPI2_NSS_PIN; +static const uint8_t MOSI = BOARD_SPI1_MOSI_PIN; +static const uint8_t MISO = BOARD_SPI1_MISO_PIN; +static const uint8_t SCK = BOARD_SPI1_SCK_PIN; + +#endif /* _VARIANT_ARDUINO_STM32_ */ \ No newline at end of file diff --git a/STM32F3/cores/maple/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103vb/wirish/boards.cpp similarity index 94% rename from STM32F3/cores/maple/wirish/boards.cpp rename to STM32F1/variants/generic_stm32f103vb/wirish/boards.cpp index a693fa6..a2867b8 100644 --- a/STM32F3/cores/maple/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103vb/wirish/boards.cpp @@ -45,7 +45,7 @@ * notice. */ -#include +#include #include #include #include @@ -120,16 +120,22 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); +#ifdef XTAL16M + // 16MHz crystal (HSE) + // in this case we additionally set the Bit 17 (PLLXTPRE=1) => then HSE clock is divided by 2 before PLL entry + RCC_BASE->CFGR |= RCC_CFGR_PLLXTPRE; +#endif + // Enable the PLL, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_PLL); while(!rcc_is_clk_ready(RCC_CLK_PLL)) @@ -144,7 +150,11 @@ static void setup_clocks(void) { * present. If no bootloader is present, the user NVIC usually starts * at the Flash base address, 0x08000000. */ -#define USER_ADDR_ROM 0x08005000 +#if defined(BOOTLOADER_maple) + #define USER_ADDR_ROM 0x08005000 +#else + #define USER_ADDR_ROM 0x08000000 +#endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; @@ -165,7 +175,7 @@ static void setup_nvic(void) { #endif } -static void adc_default_config(const adc_dev *dev) { +static void adc_default_config(adc_dev *dev) { adc_enable_single_swstart(dev); adc_set_sample_rate(dev, wirish::priv::w_adc_smp); } diff --git a/STM32F3/cores/maple/wirish/stm32f3/boards_setup.cpp b/STM32F1/variants/generic_stm32f103vb/wirish/boards_setup.cpp similarity index 54% rename from STM32F3/cores/maple/wirish/stm32f3/boards_setup.cpp rename to STM32F1/variants/generic_stm32f103vb/wirish/boards_setup.cpp index 6984419..5ea718b 100644 --- a/STM32F3/cores/maple/wirish/stm32f3/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103vb/wirish/boards_setup.cpp @@ -2,7 +2,6 @@ * The MIT License * * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,12 +25,11 @@ *****************************************************************************/ /** - * @file wirish/stm32f3/boards_setup.cpp - * @author Marti Bolivar , - * Hanspeter Portner - * @brief STM32F3 chip setup. + * @file wirish/stm32f1/boards_setup.cpp + * @author Marti Bolivar + * @brief STM32F1 chip setup. * - * This file controls how init() behaves on the STM32F3. Be very + * This file controls how init() behaves on the STM32F1. Be very * careful when changing anything here. Many of these values depend * upon each other. */ @@ -41,27 +39,41 @@ #include #include -#include -#include -#include -#include +#include +#include // Allow boards to provide a PLL multiplier. This is useful for -// e.g. STM32F300 value line MCUs, which use slower multipliers. +// e.g. STM32F100 value line MCUs, which use slower multipliers. // (We're leaving the default to RCC_PLLMUL_9 for now, since that -// works for F303 performance line MCUs, which is all that LeafLabs +// works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL -#define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #endif #endif namespace wirish { namespace priv { - static stm32f3_rcc_pll_data pll_data = {.pll_mul=BOARD_RCC_PLLMUL, .pclk_prediv=RCC_PREDIV_PCLK_DIV_1}; + static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; - __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK_DIV_1; - __weak adc_smp_rate w_adc_smp = ADC_SMPR_181_5; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif + __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; + __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; __weak void board_reset_pll(void) { // TODO @@ -71,6 +83,12 @@ namespace wirish { rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2); rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); + rcc_clk_disable(RCC_USB); + #if F_CPU == 72000000 + rcc_set_prescaler(RCC_PRESCALER_USB, RCC_USB_SYSCLK_DIV_1_5); + #elif F_CPU == 48000000 + rcc_set_prescaler(RCC_PRESCALER_USB, RCC_USB_SYSCLK_DIV_1); + #endif } __weak void board_setup_gpio(void) { @@ -78,15 +96,26 @@ namespace wirish { } __weak void board_setup_usb(void) { - SerialUSB.begin(); +#ifdef SERIAL_USB + + +#ifdef GENERIC_BOOTLOADER + //Reset the USB interface on generic boards - developed by Victor PV + gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_OUTPUT_PP); + gpio_write_bit(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit,0); + + for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin + gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING); +#endif + Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility +#endif } __weak void series_init(void) { - /* We need SYSCFG for external interrupts */ - syscfg_init(); - - /* enable floating point unit */ - fpu_enable(); + // Initialize AFIO here, too, so peripheral remaps and external + // interrupts work out of the box. + afio_init(); } + } } diff --git a/STM32F3/variants/discovery_f3/wirish/start.S b/STM32F1/variants/generic_stm32f103vb/wirish/start.S similarity index 100% rename from STM32F3/variants/discovery_f3/wirish/start.S rename to STM32F1/variants/generic_stm32f103vb/wirish/start.S diff --git a/STM32F3/variants/discovery_f3/wirish/start_c.c b/STM32F1/variants/generic_stm32f103vb/wirish/start_c.c similarity index 100% rename from STM32F3/variants/discovery_f3/wirish/start_c.c rename to STM32F1/variants/generic_stm32f103vb/wirish/start_c.c diff --git a/STM32F3/cores/maple/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103vb/wirish/syscalls.c similarity index 75% rename from STM32F3/cores/maple/wirish/syscalls.c rename to STM32F1/variants/generic_stm32f103vb/wirish/syscalls.c index a3b6d2c..ec1c34d 100644 --- a/STM32F3/cores/maple/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103vb/wirish/syscalls.c @@ -37,17 +37,18 @@ #include #include +#include /* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then * assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by * the linker */ #ifndef CONFIG_HEAP_START extern char _lm_heap_start; -#define CONFIG_HEAP_START ((caddr_t)&_lm_heap_start) +#define CONFIG_HEAP_START ((void *)&_lm_heap_start) #endif #ifndef CONFIG_HEAP_END extern char _lm_heap_end; -#define CONFIG_HEAP_END ((caddr_t)&_lm_heap_end) +#define CONFIG_HEAP_END ((void *)&_lm_heap_end) #endif /* @@ -56,9 +57,9 @@ extern char _lm_heap_end; * Get incr bytes more RAM (for use by the heap). malloc() and * friends call this function behind the scenes. */ -caddr_t _sbrk(int incr) { - static caddr_t pbreak = NULL; /* current program break */ - caddr_t ret; +void *_sbrk(int incr) { + static void * pbreak = NULL; /* current program break */ + void * ret; if (pbreak == NULL) { pbreak = CONFIG_HEAP_START; @@ -67,7 +68,7 @@ caddr_t _sbrk(int incr) { if ((CONFIG_HEAP_END - pbreak < incr) || (pbreak - CONFIG_HEAP_START < -incr)) { errno = ENOMEM; - return (caddr_t)-1; + return (void *)-1; } ret = pbreak; @@ -75,28 +76,28 @@ caddr_t _sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -105,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -154,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -164,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/generic_stm32f103z/board.cpp b/STM32F1/variants/generic_stm32f103z/board.cpp index 830479e..500f9b8 100644 --- a/STM32F1/variants/generic_stm32f103z/board.cpp +++ b/STM32F1/variants/generic_stm32f103z/board.cpp @@ -77,7 +77,6 @@ extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { uint8 gpio_bit; Pin's GPIO port bit. uint8 timer_channel; Timer channel, or 0 if none. uint8 adc_channel; Pin ADC channel, or ADCx if none. - uint8 pinMode; mode specific by pinMode call (Roger Clark added to optimize compatibility with Arduino API */ {&gpioa, &timer2, &adc1, 0, 1, 0}, /* PA0 */ @@ -231,4 +230,4 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { DEFINE_HWSERIAL(Serial2, 3); DEFINE_HWSERIAL_UART(Serial3, 4); DEFINE_HWSERIAL_UART(Serial4, 5); -#endif \ No newline at end of file +#endif diff --git a/STM32F1/variants/generic_stm32f103z/board/board.h b/STM32F1/variants/generic_stm32f103z/board/board.h index c9bf4b5..fe48567 100644 --- a/STM32F1/variants/generic_stm32f103z/board/board.h +++ b/STM32F1/variants/generic_stm32f103z/board/board.h @@ -102,6 +102,16 @@ #define BOARD_USB_DISC_DEV GPIOC #define BOARD_USB_DISC_BIT 12 +/* + * SDIO Pins + */ +#define BOARD_SDIO_D0 PC8 +#define BOARD_SDIO_D1 PC9 +#define BOARD_SDIO_D2 PC10 +#define BOARD_SDIO_D3 PC11 +#define BOARD_SDIO_CLK PC12 +#define BOARD_SDIO_CMD PD2 + /* Pin aliases: these give the GPIO port/bit for each pin as an * enum. These are optional, but recommended. They make it easier to * write code using low-level GPIO functionality. */ diff --git a/STM32F1/variants/generic_stm32f103z/wirish/boards.cpp b/STM32F1/variants/generic_stm32f103z/wirish/boards.cpp index fcb85b2..93ae231 100644 --- a/STM32F1/variants/generic_stm32f103z/wirish/boards.cpp +++ b/STM32F1/variants/generic_stm32f103z/wirish/boards.cpp @@ -120,12 +120,12 @@ static void setup_clocks(void) { // Clear clock readiness interrupt flags and turn off clock // readiness interrupts. RCC_BASE->CIR = 0x00000000; - +#if !USE_HSI_CLOCK // Enable HSE, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_HSE); while (!rcc_is_clk_ready(RCC_CLK_HSE)) ; - +#endif // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); rcc_configure_pll(&wirish::priv::w_board_pll_cfg); @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/generic_stm32f103z/wirish/boards_setup.cpp b/STM32F1/variants/generic_stm32f103z/wirish/boards_setup.cpp index e2cfe4a..6cc457e 100644 --- a/STM32F1/variants/generic_stm32f103z/wirish/boards_setup.cpp +++ b/STM32F1/variants/generic_stm32f103z/wirish/boards_setup.cpp @@ -48,10 +48,18 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #if !USE_HSI_CLOCK + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif + #else + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 #endif #endif @@ -59,7 +67,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; +#if !USE_HSI_CLOCK __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; +#else + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSI_DIV_2, &pll_data}; +#endif __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; diff --git a/STM32F1/variants/generic_stm32f103z/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103z/wirish/syscalls.c index d42536c..91ed5a1 100644 --- a/STM32F1/variants/generic_stm32f103z/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103z/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/hytiny_stm32f103t/board/board.h b/STM32F1/variants/hytiny_stm32f103t/board/board.h index 194b2e5..179e5e5 100644 --- a/STM32F1/variants/hytiny_stm32f103t/board/board.h +++ b/STM32F1/variants/hytiny_stm32f103t/board/board.h @@ -36,7 +36,7 @@ #ifndef _BOARD_GENERIC_STM32F103C_H_ #define _BOARD_GENERIC_STM32F103C_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_NR_USARTS 2 diff --git a/STM32F1/variants/hytiny_stm32f103t/wirish/boards.cpp b/STM32F1/variants/hytiny_stm32f103t/wirish/boards.cpp index 0a358ee..d7b6edc 100644 --- a/STM32F1/variants/hytiny_stm32f103t/wirish/boards.cpp +++ b/STM32F1/variants/hytiny_stm32f103t/wirish/boards.cpp @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/hytiny_stm32f103t/wirish/boards_setup.cpp b/STM32F1/variants/hytiny_stm32f103t/wirish/boards_setup.cpp index df39347..9051989 100644 --- a/STM32F1/variants/hytiny_stm32f103t/wirish/boards_setup.cpp +++ b/STM32F1/variants/hytiny_stm32f103t/wirish/boards_setup.cpp @@ -48,11 +48,15 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 - #endif + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif #endif namespace wirish { diff --git a/STM32F1/variants/hytiny_stm32f103t/wirish/syscalls.c b/STM32F1/variants/hytiny_stm32f103t/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/hytiny_stm32f103t/wirish/syscalls.c +++ b/STM32F1/variants/hytiny_stm32f103t/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/maple/board/board.h b/STM32F1/variants/maple/board/board.h index caebcc7..5a09286 100644 --- a/STM32F1/variants/maple/board/board.h +++ b/STM32F1/variants/maple/board/board.h @@ -34,7 +34,7 @@ #define _BOARD_MAPLE_H_ /* 72 MHz -> 72 cycles per microsecond. */ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) /* Roger clark diff --git a/STM32F1/variants/maple/wirish/boards.cpp b/STM32F1/variants/maple/wirish/boards.cpp index fcb85b2..ef1f2ad 100644 --- a/STM32F1/variants/maple/wirish/boards.cpp +++ b/STM32F1/variants/maple/wirish/boards.cpp @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/maple/wirish/boards_setup.cpp b/STM32F1/variants/maple/wirish/boards_setup.cpp index 1071d6d..d1170cd 100644 --- a/STM32F1/variants/maple/wirish/boards_setup.cpp +++ b/STM32F1/variants/maple/wirish/boards_setup.cpp @@ -48,11 +48,15 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 - #endif + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif #endif namespace wirish { diff --git a/STM32F1/variants/maple/wirish/syscalls.c b/STM32F1/variants/maple/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/maple/wirish/syscalls.c +++ b/STM32F1/variants/maple/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/maple_mini/board/board.h b/STM32F1/variants/maple_mini/board/board.h index b7a54a8..9064807 100644 --- a/STM32F1/variants/maple_mini/board/board.h +++ b/STM32F1/variants/maple_mini/board/board.h @@ -36,7 +36,7 @@ #ifndef _BOARD_MAPLE_MINI_H_ #define _BOARD_MAPLE_MINI_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ #define BOARD_NR_USARTS 3 @@ -71,6 +71,8 @@ #define BOARD_USB_DISC_DEV GPIOB #define BOARD_USB_DISC_BIT 9 +#define LED_BUILTIN PB1 + enum { PB11, PB10, PB2, PB0, PA7, PA6, PA5, PA4, PA3, PA2, PA1, PA0, PC15, PC14, PC13, PB7, PB6, PB5, PB4, PB3, PA15, PA14, PA13, PA12, PA11, PA10, PA9, diff --git a/STM32F1/variants/maple_mini/wirish/boards.cpp b/STM32F1/variants/maple_mini/wirish/boards.cpp index 5274e7a..7b7e9a6 100644 --- a/STM32F1/variants/maple_mini/wirish/boards.cpp +++ b/STM32F1/variants/maple_mini/wirish/boards.cpp @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/maple_mini/wirish/boards_setup.cpp b/STM32F1/variants/maple_mini/wirish/boards_setup.cpp index df39347..9051989 100644 --- a/STM32F1/variants/maple_mini/wirish/boards_setup.cpp +++ b/STM32F1/variants/maple_mini/wirish/boards_setup.cpp @@ -48,11 +48,15 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 - #endif + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif #endif namespace wirish { diff --git a/STM32F1/variants/maple_mini/wirish/syscalls.c b/STM32F1/variants/maple_mini/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/maple_mini/wirish/syscalls.c +++ b/STM32F1/variants/maple_mini/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/maple_ret6/board.cpp b/STM32F1/variants/maple_ret6/board.cpp index fb92779..2b4e2e4 100644 --- a/STM32F1/variants/maple_ret6/board.cpp +++ b/STM32F1/variants/maple_ret6/board.cpp @@ -77,7 +77,6 @@ extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { uint8 gpio_bit; Pin's GPIO port bit. uint8 timer_channel; Timer channel, or 0 if none. uint8 adc_channel; Pin ADC channel, or ADCx if none. - uint8 pinMode; mode specific by pinMode call (Roger Clark added to optimize compatibility with Arduino API */ /* Top header */ @@ -175,4 +174,4 @@ DEFINE_HWSERIAL(Serial1, 1); DEFINE_HWSERIAL(Serial2, 2); DEFINE_HWSERIAL(Serial3, 3); DEFINE_HWSERIAL_UART(Serial4, 4); -DEFINE_HWSERIAL_UART(Serial5, 5); \ No newline at end of file +DEFINE_HWSERIAL_UART(Serial5, 5); diff --git a/STM32F1/variants/maple_ret6/board/board.h b/STM32F1/variants/maple_ret6/board/board.h index 86d94f0..4f6fae7 100644 --- a/STM32F1/variants/maple_ret6/board/board.h +++ b/STM32F1/variants/maple_ret6/board/board.h @@ -102,6 +102,16 @@ #define BOARD_USB_DISC_DEV GPIOC #define BOARD_USB_DISC_BIT 12 +/* + * SDIO Pins + */ +#define BOARD_SDIO_D0 PC8 +#define BOARD_SDIO_D1 PC9 +#define BOARD_SDIO_D2 PC10 +#define BOARD_SDIO_D3 PC11 +#define BOARD_SDIO_CLK PC12 +#define BOARD_SDIO_CMD PD2 + /* Pin aliases: these give the GPIO port/bit for each pin as an * enum. These are optional, but recommended. They make it easier to * write code using low-level GPIO functionality. */ @@ -117,4 +127,4 @@ enum { //15 16 17 18 19 20 21 22 23 24 25 26 27 28 -//29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 \ No newline at end of file +//29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 diff --git a/STM32F1/variants/maple_ret6/wirish/boards.cpp b/STM32F1/variants/maple_ret6/wirish/boards.cpp index fcb85b2..ef1f2ad 100644 --- a/STM32F1/variants/maple_ret6/wirish/boards.cpp +++ b/STM32F1/variants/maple_ret6/wirish/boards.cpp @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/maple_ret6/wirish/boards_setup.cpp b/STM32F1/variants/maple_ret6/wirish/boards_setup.cpp index 1071d6d..d1170cd 100644 --- a/STM32F1/variants/maple_ret6/wirish/boards_setup.cpp +++ b/STM32F1/variants/maple_ret6/wirish/boards_setup.cpp @@ -48,11 +48,15 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 - #endif + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif #endif namespace wirish { diff --git a/STM32F1/variants/maple_ret6/wirish/syscalls.c b/STM32F1/variants/maple_ret6/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/maple_ret6/wirish/syscalls.c +++ b/STM32F1/variants/maple_ret6/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/microduino/board/board.h b/STM32F1/variants/microduino/board/board.h index 2a1295f..0c06363 100644 --- a/STM32F1/variants/microduino/board/board.h +++ b/STM32F1/variants/microduino/board/board.h @@ -37,7 +37,7 @@ #ifndef _BOARD_MICRODUINO_STM32_H_ #define _BOARD_MICRODUINO_STM32_H_ -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ /* Roger Clark. diff --git a/STM32F1/variants/microduino/wirish/boards.cpp b/STM32F1/variants/microduino/wirish/boards.cpp index fcb85b2..ef1f2ad 100644 --- a/STM32F1/variants/microduino/wirish/boards.cpp +++ b/STM32F1/variants/microduino/wirish/boards.cpp @@ -147,11 +147,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/microduino/wirish/boards_setup.cpp b/STM32F1/variants/microduino/wirish/boards_setup.cpp index e899843..1f1ec5e 100644 --- a/STM32F1/variants/microduino/wirish/boards_setup.cpp +++ b/STM32F1/variants/microduino/wirish/boards_setup.cpp @@ -48,11 +48,15 @@ // works for F103 performance line MCUs, which is all that LeafLabs // currently officially supports). #ifndef BOARD_RCC_PLLMUL - #if F_CPU==72000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 - #elif F_CPU==48000000 - #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 - #endif + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #elif F_CPU==16000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_2 + #endif #endif namespace wirish { diff --git a/STM32F1/variants/microduino/wirish/syscalls.c b/STM32F1/variants/microduino/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/microduino/wirish/syscalls.c +++ b/STM32F1/variants/microduino/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F1/variants/nucleo_f103rb/board/board.h b/STM32F1/variants/nucleo_f103rb/board/board.h index 02f46d9..5c7ece7 100644 --- a/STM32F1/variants/nucleo_f103rb/board/board.h +++ b/STM32F1/variants/nucleo_f103rb/board/board.h @@ -33,7 +33,7 @@ #ifndef _BOARD_MAPLE_H_ #define _BOARD_MAPLE_H_ #define _BOARD_NUCLEOF103RB_ 1 // hack for HardwareSerial.cpp for a new order of serials -#define CYCLES_PER_MICROSECOND 72 +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) #define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ /* Roger clark. Removed defines for LED pin and Button pin as they are not Arduino API defines */ @@ -102,11 +102,8 @@ /** * Note: there is no USB in this board. */ - // Roger Clark. These USB disconnect pin definitions have been added as a temporary fix in order that the this board compiles - // following changes to add usb serial to other boards - // I will remove them when the code in the core usb_serial.cpp has been tidied up so that they are no longer needed. -#define BOARD_USB_DISC_DEV GPIOB -#define BOARD_USB_DISC_BIT 10 +#define BOARD_USB_DISC_DEV NULL +#define BOARD_USB_DISC_BIT NULL /* Pin aliases: these give the GPIO port/bit for each pin as an * enum. These are optional, but recommended. They make it easier to diff --git a/STM32F1/variants/nucleo_f103rb/wirish/boards.cpp b/STM32F1/variants/nucleo_f103rb/wirish/boards.cpp index f38cbf6..61368ce 100644 --- a/STM32F1/variants/nucleo_f103rb/wirish/boards.cpp +++ b/STM32F1/variants/nucleo_f103rb/wirish/boards.cpp @@ -149,11 +149,7 @@ static void setup_clocks(void) { #if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 #else - #if defined(BOOTLOADER_robotis) - #define USER_ADDR_ROM 0x08003000 - #else - #define USER_ADDR_ROM 0x08000000 - #endif + #define USER_ADDR_ROM 0x08000000 #endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/STM32F1/variants/nucleo_f103rb/wirish/syscalls.c b/STM32F1/variants/nucleo_f103rb/wirish/syscalls.c index d5f2d9f..ec1c34d 100644 --- a/STM32F1/variants/nucleo_f103rb/wirish/syscalls.c +++ b/STM32F1/variants/nucleo_f103rb/wirish/syscalls.c @@ -76,28 +76,28 @@ void *_sbrk(int incr) { return ret; } -__weak int _open(const char *path, int flags, ...) { +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { return 1; } -__weak int _close(int fd) { +__weak int _close(int fd __attribute__((unused))) { return 0; } -__weak int _fstat(int fd, struct stat *st) { +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { st->st_mode = S_IFCHR; return 0; } -__weak int _isatty(int fd) { +__weak int _isatty(int fd __attribute__((unused))) { return 1; } -__weak int isatty(int fd) { +__weak int isatty(int fd __attribute__((unused))) { return 1; } -__weak int _lseek(int fd, off_t pos, int whence) { +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { return -1; } @@ -106,13 +106,13 @@ __weak unsigned char getch(void) { } -__weak int _read(int fd, char *buf, size_t cnt) { +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { *buf = getch(); return 1; } -__weak void putch(unsigned char c) { +__weak void putch(unsigned char c __attribute__((unused))) { } __weak void cgets(char *s, int bufsize) { @@ -155,7 +155,7 @@ __weak void cgets(char *s, int bufsize) { return; } -__weak int _write(int fd, const char *buf, size_t cnt) { +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { int i; for (i = 0; i < cnt; i++) @@ -165,12 +165,12 @@ __weak int _write(int fd, const char *buf, size_t cnt) { } /* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f) { +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { cgets(s, bufsize); return s; } -__weak void _exit(int exitcode) { +__weak void _exit(int exitcode __attribute__((unused))) { while (1) ; } diff --git a/STM32F3/README.md b/STM32F3/README.md deleted file mode 100644 index 75cd5a4..0000000 --- a/STM32F3/README.md +++ /dev/null @@ -1,45 +0,0 @@ -STM32F3 files have been supplied by Frank-Michael Krause. - -The API is not as up to date as in the STM F103 files. -It looks like this port is as the F103 files orginally were when I started work on the project. -The API is for pre- Arduino 1.0 and doesn't include a lot of functions in the 1.0 API, and the class inheritance will -be different in a number of places, most importantly in the Serial class. -Specifically Stream.cpp / .h are not present in this port. - - - --------------------- Details from Frank-Michael ---------------------------- - -This port of libmaple for Arduino-IDE is based on the inofficial F3 branch -of libmaple found on -https://github.com/ventosus/libmaple/tree/F3 -and supports at the moment the STM32F3Discovery board with programming via ST-link. -Linker is configured for linking to flash, not to RAM - -Changes by Frank-Michael Krause (mich dot krause at web dot de): - -- renaming some stm32f3 related files because the Arduino build system copy all objects to same directory so the source file names must be different -- selected the correct startup modules and linker scripts for board variant stm32f3discovery - -Notes: - -- the pin names as noted on stm32f3discovery board (PA0, PA1, ..., PF10) can be used as pin id -- usb is untested because I haven't used it really -- There are some libraries and examples related to the STM32F3discovery board. - They are commented mostly in german only because I wrote them for use at robotic club of a secondary school - and the kids like to have the documentation in german. - - gyro: Interface library for the gyro-chip of the stm32f3discovery, setup the gyro in FIFO mode and so - requiring update calls only every < 120ms - lsm303: Interface library for Acceleration sensor of the stm32f3discovery, magnetometer not yet supported (writing this driver is currently under work by a student at school) - ringbuffer: Class impelentig a ringbuffer with functions for adding time stampes per added element, averaging functions, accessing the stored data like an array - roboter: several functionalities needed to program a robot: - - dc motor control as known from Lego NXC language - - support for HC-SR04 ultrasonic sensors driven by interrupt or blocking direct measurement - - function timers based on timer interrupt - - modul for interfacing a 24Cxx I2C eeprom chip - - - - - diff --git a/STM32F3/boards.txt b/STM32F3/boards.txt deleted file mode 100644 index 82b2bc5..0000000 --- a/STM32F3/boards.txt +++ /dev/null @@ -1,33 +0,0 @@ -# - -############################################################## -discovery_f3.name=STM32F3Discovery - -discovery_f3.upload.tool=stlink -discovery_f3.upload.protocol=stlink - -#discovery_f407.upload.use_1200bps_touch=false -discovery_f3.upload.file_type=bin -discovery_f3.upload.ram.maximum_size=17000 -discovery_f3.upload.flash.maximum_size=108000 -discovery_f3.upload.maximum_size=108000 - -#discovery_f3.upload.usbID=1EAF:0003 -#discovery_f3.upload.altID=1 -#discovery_f3.upload.auto_reset=true - -discovery_f3.build.mcu=cortex-m3 -discovery_f3.build.f_cpu=72000000L -discovery_f3.build.core=maple -discovery_f3.build.extra_flags=-DMCU_STM32F303VC -mthumb -DSTM32_XL_DENSITY -march=armv7-m -DSTM32F3 -DF303VC -DBOARD_discovery_f3 -discovery_f3.build.ldscript=ld/jtag.ld -discovery_f3.build.variant=discovery_f3 -discovery_f3.build.variant_system_lib=lib_f3.a -discovery_f3.build.vect=VECT_TAB_BASE -discovery_f3.build.density=STM32_XL_DENSITY -discovery_f3.build.error_led_port=GPIOE -discovery_f3.build.error_led_pin=8 -discovery_f3.build.board=STM32F3Discovery - -############################################################## - diff --git a/STM32F3/cores/maple/Arduino.h b/STM32F3/cores/maple/Arduino.h deleted file mode 100644 index 7278f89..0000000 --- a/STM32F3/cores/maple/Arduino.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef Arduino_h -#define Arduino_h -#include "WProgram.h" -#endif diff --git a/STM32F3/cores/maple/libmaple/adc.c b/STM32F3/cores/maple/libmaple/adc.c deleted file mode 100644 index 630a8a8..0000000 --- a/STM32F3/cores/maple/libmaple/adc.c +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/adc.c - * @author Marti Bolivar , - * Perry Hung , - * F3-port by Hanspeter Portner - * @brief Analog to digital converter routines - */ - -#include -#include -#include - -/** - * @brief Initialize an ADC peripheral. - * - * Initializes the RCC clock line for the given peripheral. Resets - * ADC device registers. - * - * @param dev ADC peripheral to initialize - */ -void adc_init(const adc_dev *dev) { - rcc_clk_enable(dev->clk_id); - rcc_reset_dev(dev->clk_id); -} diff --git a/STM32F3/cores/maple/libmaple/bkp.c b/STM32F3/cores/maple/libmaple/bkp.c deleted file mode 100644 index c837307..0000000 --- a/STM32F3/cores/maple/libmaple/bkp.c +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/bkp.c - * @author F3-port by Hanspeter Portner - * @brief Backup register support (STM32F1 & STM32F3 only). - */ - -#include -#include -#include - -bkp_dev bkp = { - .regs = BKP_BASE, -}; -/** Backup device. */ -const bkp_dev *BKP = &bkp; - -void bkp_enable_writes(void) { - *bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 1; -} - -void bkp_disable_writes(void) { - *bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 0; -} - -uint16 bkp_read(uint8 reg) { - __io uint32* dr = bkp_data_register(reg); - if (!dr) { - ASSERT(0); /* nonexistent register */ - return 0; - } - return (uint16)*dr; -} - -void bkp_write(uint8 reg, uint16 val) { - __io uint32* dr = bkp_data_register(reg); - if (!dr) { - ASSERT(0); /* nonexistent register */ - return; - } - *dr = (uint32)val; -} - diff --git a/STM32F3/cores/maple/libmaple/dac.c b/STM32F3/cores/maple/libmaple/dac.c deleted file mode 100644 index d802d2b..0000000 --- a/STM32F3/cores/maple/libmaple/dac.c +++ /dev/null @@ -1,120 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Bryan Newbold. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/dac.c - * @brief Digital to analog converter support. - */ - -#include -#include -#include - -#if STM32_HAVE_DAC -dac_dev dac = { - .regs = DAC_BASE, -}; -const dac_dev *DAC = &dac; -#endif - -/** - * @brief Initialize the digital to analog converter - * @param dev DAC device - * @param flags Flags: - * DAC_CH1: Enable channel 1 - * DAC_CH2: Enable channel 2 - * @sideeffect May set PA4 or PA5 to INPUT_ANALOG - */ -void dac_init(const dac_dev *dev, uint32 flags) { - /* First turn on the clock */ - rcc_clk_enable(RCC_DAC); - rcc_reset_dev(RCC_DAC); - - if (flags & DAC_CH1) { - dac_enable_channel(dev, 1); - } - - if (flags & DAC_CH2) { - dac_enable_channel(dev, 2); - } -} - -/** - * @brief Write a 12-bit value to the DAC to output - * @param dev DAC device - * @param channel channel to select (1 or 2) - * @param val value to write - */ -void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val) { - switch(channel) { - case 1: - dev->regs->DHR12R1 = DAC_DHR12R1_DACC1DHR & val; - break; - case 2: - dev->regs->DHR12R2 = DAC_DHR12R2_DACC2DHR & val; - break; - } -} - -/** - * @brief Enable a DAC channel - * @param dev DAC device - * @param channel channel to enable, either 1 or 2 - * @sideeffect May change pin mode of PA4 or PA5 - */ -void dac_enable_channel(const dac_dev *dev, uint8 channel) { - /* - * Setup ANALOG mode on PA4 and PA5. This mapping is consistent - * across all supported STM32s with a DAC. - */ - switch (channel) { - case 1: - gpio_set_mode(GPIOA, 4, GPIO_MODE_ANALOG); - dev->regs->CR |= DAC_CR_EN1; - break; - case 2: - gpio_set_mode(GPIOA, 5, GPIO_MODE_ANALOG); - dev->regs->CR |= DAC_CR_EN2; - break; - } -} - -/** - * @brief Disable a DAC channel - * @param dev DAC device - * @param channel channel to disable, either 1 or 2 - */ -void dac_disable_channel(const dac_dev *dev, uint8 channel) { - switch (channel) { - case 1: - dev->regs->CR &= ~DAC_CR_EN1; - break; - case 2: - dev->regs->CR &= ~DAC_CR_EN2; - break; - } -} diff --git a/STM32F3/cores/maple/libmaple/dma.c b/STM32F3/cores/maple/libmaple/dma.c deleted file mode 100644 index d13de10..0000000 --- a/STM32F3/cores/maple/libmaple/dma.c +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/dma.c - * @author Marti Bolivar ; - * Original implementation by Michael Hope - * @brief Portable DMA routines. - */ - -#include -#include "dma_private.h" -#include "stm32_private.h" - -/* - * Convenience routines - */ - -/** - * @brief Initialize a DMA device. - * @param dev Device to initialize. - */ -void dma_init(dma_dev *dev) { - rcc_clk_enable(dev->clk_id); -} - -/* - * Private API - */ - -enum dma_atype _dma_addr_type(__io void *addr) { - switch (stm32_block_purpose((void*)addr)) { - /* Notice we're treating the code block as memory here. That's - * correct for addresses in Flash and in [0x0, 0x7FFFFFF] - * (provided that those addresses are aliased to Flash, SRAM, or - * FSMC, depending on BOOT[01] and possibly SYSCFG_MEMRMP). It's - * not correct for other addresses in the code block, but those - * will (hopefully) just fail-fast with transfer or bus errors. If - * lots of people get confused, it might be worth being more - * careful here. */ - case STM32_BLOCK_CODE: /* Fall through */ - case STM32_BLOCK_SRAM: /* ... */ - case STM32_BLOCK_FSMC_1_2: /* ... */ - case STM32_BLOCK_FSMC_3_4: - return DMA_ATYPE_MEM; - case STM32_BLOCK_PERIPH: - return DMA_ATYPE_PER; - case STM32_BLOCK_FSMC_REG: /* Fall through */ - /* Is this right? I can't think of a reason to DMA into or out - * of the FSMC registers. [mbolivar] */ - case STM32_BLOCK_UNUSED: /* ... */ - case STM32_BLOCK_CORTEX_INTERNAL: /* ... */ - return DMA_ATYPE_OTHER; - default: - ASSERT(0); /* Can't happen */ - return DMA_ATYPE_OTHER; - } -} diff --git a/STM32F3/cores/maple/libmaple/exc.S b/STM32F3/cores/maple/libmaple/exc.S deleted file mode 100644 index 7631e48..0000000 --- a/STM32F3/cores/maple/libmaple/exc.S +++ /dev/null @@ -1,101 +0,0 @@ -/* ***************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * ****************************************************************************/ - -# On an exception, push a fake stack thread mode stack frame and redirect -# thread execution to a thread mode error handler - -# From RM008: -# The SP is decremented by eight words by the completion of the stack push. -# Figure 5-1 shows the contents of the stack after an exception pre-empts the -# current program flow. -# -# Old SP--> -# xPSR -# PC -# LR -# r12 -# r3 -# r2 -# r1 -# SP--> r0 - -.text -.globl __exc_hardfault -.globl __exc_nmi -.globl __exc_hardfault -.globl __exc_memmanage -.globl __exc_busfault -.globl __exc_usagefault - -.code 16 -.thumb_func -__exc_nmi: - mov r0, #1 - b __default_exc - -.thumb_func -__exc_hardfault: - mov r0, #2 - b __default_exc - -.thumb_func -__exc_memmanage: - mov r0, #3 - b __default_exc - -.thumb_func -__exc_busfault: - mov r0, #4 - b __default_exc - -.thumb_func -__exc_usagefault: - mov r0, #5 - b __default_exc - -.thumb_func -__default_exc: - ldr r2, NVIC_CCR @ Enable returning to thread mode even if there are - mov r1 ,#1 @ pending exceptions. See flag NONEBASETHRDENA. - str r1, [r2] - cpsid i @ Disable global interrupts - ldr r2, SYSTICK_CSR @ Disable systick handler - mov r1, #0 - str r1, [r2] - ldr r1, CPSR_MASK @ Set default CPSR - push {r1} - ldr r1, TARGET_PC @ Set target pc - push {r1} - sub sp, sp, #24 @ Don't care - ldr r1, EXC_RETURN @ Return to thread mode - mov lr, r1 - bx lr @ Exception exit - -.align 4 -CPSR_MASK: .word 0x61000000 -EXC_RETURN: .word 0xFFFFFFF9 -TARGET_PC: .word __error -NVIC_CCR: .word 0xE000ED14 @ NVIC configuration control register -SYSTICK_CSR: .word 0xE000E010 @ Systick control register - diff --git a/STM32F3/cores/maple/libmaple/exti.c b/STM32F3/cores/maple/libmaple/exti.c deleted file mode 100644 index c35072c..0000000 --- a/STM32F3/cores/maple/libmaple/exti.c +++ /dev/null @@ -1,293 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/exti.c - * @brief External interrupt control routines - */ - -#include -#include -#include -#include - -static inline void dispatch_single_exti(uint32 exti_num); -static inline void dispatch_extis(uint32 start, uint32 stop); - -/* - * Internal state - */ - -typedef struct exti_channel { - void (*handler)(void *); - void *arg; -} exti_channel; - -static exti_channel exti_channels[] = { - { .handler = NULL, .arg = NULL }, // EXTI0 - { .handler = NULL, .arg = NULL }, // EXTI1 - { .handler = NULL, .arg = NULL }, // EXTI2 - { .handler = NULL, .arg = NULL }, // EXTI3 - { .handler = NULL, .arg = NULL }, // EXTI4 - { .handler = NULL, .arg = NULL }, // EXTI5 - { .handler = NULL, .arg = NULL }, // EXTI6 - { .handler = NULL, .arg = NULL }, // EXTI7 - { .handler = NULL, .arg = NULL }, // EXTI8 - { .handler = NULL, .arg = NULL }, // EXTI9 - { .handler = NULL, .arg = NULL }, // EXTI10 - { .handler = NULL, .arg = NULL }, // EXTI11 - { .handler = NULL, .arg = NULL }, // EXTI12 - { .handler = NULL, .arg = NULL }, // EXTI13 - { .handler = NULL, .arg = NULL }, // EXTI14 - { .handler = NULL, .arg = NULL }, // EXTI15 -}; - -/* - * Portable routines - */ - -/** - * @brief Register a handler to run upon external interrupt. - * - * This function assumes that the interrupt request corresponding to - * the given external interrupt is masked. - * - * @param num External interrupt line number. - * @param port Port to use as source input for external interrupt. - * @param handler Function handler to execute when interrupt is triggered. - * @param mode Type of transition to trigger on, one of: - * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. - * @see exti_num - * @see exti_cfg - * @see voidFuncPtr - * @see exti_trigger_mode - */ -void exti_attach_interrupt(exti_num num, - exti_cfg port, - voidFuncPtr handler, - exti_trigger_mode mode) { - // Call callback version with arg being null - exti_attach_callback(num, port, (voidArgumentFuncPtr)handler, NULL, mode); -} - -/** - * @brief Register a handler with an argument to run upon external interrupt. - * - * This function assumes that the interrupt request corresponding to - * the given external interrupt is masked. - * - * @param num External interrupt line number. - * @param port Port to use as source input for external interrupt. - * @param handler Function handler to execute when interrupt is triggered. - * @param arg Argument to pass to the interrupt handler. - * @param mode Type of transition to trigger on, one of: - * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. - * @see exti_num - * @see exti_cfg - * @see voidFuncPtr - * @see exti_trigger_mode - */ -void exti_attach_callback(exti_num num, - exti_cfg port, - voidArgumentFuncPtr handler, - void *arg, - exti_trigger_mode mode) { - ASSERT(handler); - - /* Register the handler */ - exti_channels[num].handler = handler; - exti_channels[num].arg = arg; - - /* Set trigger mode */ - switch (mode) { - case EXTI_RISING: - bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1); - break; - case EXTI_FALLING: - bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1); - break; - case EXTI_RISING_FALLING: - bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1); - bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1); - break; - } - - /* Use the chip-specific exti_select() to map num to port */ - exti_select(num, port); - - /* Unmask external interrupt request */ - bb_peri_set_bit(&EXTI_BASE->IMR, num, 1); - - /* Enable the interrupt line */ - switch(num) - { - case EXTI0: - nvic_irq_enable(NVIC_EXTI0); - break; - case EXTI1: - nvic_irq_enable(NVIC_EXTI1); - break; - case EXTI2: - nvic_irq_enable(NVIC_EXTI2); - break; - case EXTI3: - nvic_irq_enable(NVIC_EXTI3); - break; - case EXTI4: - nvic_irq_enable(NVIC_EXTI4); - break; - case EXTI5: - case EXTI6: - case EXTI7: - case EXTI8: - case EXTI9: - nvic_irq_enable(NVIC_EXTI_9_5); - break; - case EXTI10: - case EXTI11: - case EXTI12: - case EXTI13: - case EXTI14: - case EXTI15: - nvic_irq_enable(NVIC_EXTI_15_10); - break; - } -} - -/** - * @brief Unregister an external interrupt handler - * @param num External interrupt line to disable. - * @see exti_num - */ -void exti_detach_interrupt(exti_num num) { - /* First, mask the interrupt request */ - bb_peri_set_bit(&EXTI_BASE->IMR, num, 0); - - /* Then, clear the trigger selection registers */ - bb_peri_set_bit(&EXTI_BASE->FTSR, num, 0); - bb_peri_set_bit(&EXTI_BASE->RTSR, num, 0); - - /* Finally, unregister the user's handler */ - exti_channels[num].handler = NULL; - exti_channels[num].arg = NULL; -} - -/* - * Private routines - */ - -void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port) { - uint32 shift = 4 * (num % 4); - uint32 cr = *exti_cr; - cr &= ~(0xF << shift); - cr |= port << shift; - *exti_cr = cr; -} - -/* - * Interrupt handlers - */ - -void __irq_exti0(void) { - dispatch_single_exti(EXTI0); -} - -void __irq_exti1(void) { - dispatch_single_exti(EXTI1); -} - -void __irq_exti2(void) { - dispatch_single_exti(EXTI2); - // FIXME handle capatitive touch IRQ on F302/303 -} - -void __irq_exti3(void) { - dispatch_single_exti(EXTI3); -} - -void __irq_exti4(void) { - dispatch_single_exti(EXTI4); -} - -void __irq_exti9_5(void) { - dispatch_extis(5, 9); -} - -void __irq_exti15_10(void) { - dispatch_extis(10, 15); -} - -/* - * Auxiliary functions - */ - -/* Clear the pending bits for EXTIs whose bits are set in exti_msk. - * - * If a pending bit is cleared as the last instruction in an ISR, it - * won't actually be cleared in time and the ISR will fire again. To - * compensate, this function NOPs for 2 cycles after clearing the - * pending bits to ensure it takes effect. */ -static __always_inline void clear_pending_msk(uint32 exti_msk) { - EXTI_BASE->PR = exti_msk; - asm volatile("nop"); - asm volatile("nop"); -} - -/* This dispatch routine is for non-multiplexed EXTI lines only; i.e., - * it doesn't check EXTI_PR. */ -static __always_inline void dispatch_single_exti(uint32 exti) { - voidArgumentFuncPtr handler = exti_channels[exti].handler; - - if (!handler) { - return; - } - - handler(exti_channels[exti].arg); - clear_pending_msk(1U << exti); -} - -/* Dispatch routine for EXTIs which share an IRQ. */ -static __always_inline void dispatch_extis(uint32 start, uint32 stop) { - uint32 pr = EXTI_BASE->PR; - uint32 handled_msk = 0; - uint32 exti; - - /* Dispatch user handlers for pending EXTIs. */ - for (exti = start; exti <= stop; exti++) { - uint32 eb = (1U << exti); - if (pr & eb) { - voidArgumentFuncPtr handler = exti_channels[exti].handler; - if (handler) { - handler(exti_channels[exti].arg); - handled_msk |= eb; - } - } - } - - /* Clear the pending bits for handled EXTIs. */ - clear_pending_msk(handled_msk); -} diff --git a/STM32F3/cores/maple/libmaple/exti_private.h b/STM32F3/cores/maple/libmaple/exti_private.h deleted file mode 100644 index 4f0a4cf..0000000 --- a/STM32F3/cores/maple/libmaple/exti_private.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -#ifndef _LIBMAPLE_EXTI_PRIVATE_H_ -#define _LIBMAPLE_EXTI_PRIVATE_H_ - -#include - -void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port); - -#endif diff --git a/STM32F3/cores/maple/libmaple/flash.c b/STM32F3/cores/maple/libmaple/flash.c deleted file mode 100644 index c57bbbf..0000000 --- a/STM32F3/cores/maple/libmaple/flash.c +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/flash.c - * @brief Flash management functions - */ - -#include -#include - -/** - * @brief Set flash wait states - * - * Note that not all wait states are available on every MCU. See the - * Flash programming manual for your MCU for restrictions on the - * allowed value of wait_states for a given system clock (SYSCLK) - * frequency. - * - * @param wait_states number of wait states (one of - * FLASH_WAIT_STATE_0, FLASH_WAIT_STATE_1, - * ..., FLASH_WAIT_STATE_7). - */ -void flash_set_latency(uint32 wait_states) { - uint32 val = FLASH_BASE->ACR; - - val &= ~FLASH_ACR_LATENCY; - val |= wait_states; - - FLASH_BASE->ACR = val; -} diff --git a/STM32F3/cores/maple/libmaple/gpio.c b/STM32F3/cores/maple/libmaple/gpio.c deleted file mode 100644 index 6e63d2f..0000000 --- a/STM32F3/cores/maple/libmaple/gpio.c +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/gpio.c - * @brief Generic STM32 GPIO support. - */ - -#include -#include - -/* - * GPIO routines - */ - -/** - * Initialize a GPIO device. - * - * Enables the clock for and resets the given device. - * - * @param dev GPIO device to initialize. - */ -void gpio_init(gpio_dev *dev) { - rcc_clk_enable(dev->clk_id); - rcc_reset_dev(dev->clk_id); -} diff --git a/STM32F3/cores/maple/libmaple/i2c.c b/STM32F3/cores/maple/libmaple/i2c.c deleted file mode 100644 index 87b96d1..0000000 --- a/STM32F3/cores/maple/libmaple/i2c.c +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/i2c.c - * @author Perry Hung , - * F3-port by Hanspeter Portner - * @brief Inter-Integrated Circuit (I2C) support. - * - * Currently, only master mode is supported. - */ - -#include "i2c_private.h" - -#include -#include -#include -#include -#include -#include - -#include - -void i2c_init(i2c_dev *dev) { - rcc_reset_dev(dev->clk_id); - rcc_clk_enable(dev->clk_id); -} diff --git a/STM32F3/cores/maple/libmaple/i2c_private.h b/STM32F3/cores/maple/libmaple/i2c_private.h deleted file mode 100644 index 4857955..0000000 --- a/STM32F3/cores/maple/libmaple/i2c_private.h +++ /dev/null @@ -1,75 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifndef _LIBMAPLE_I2C_PRIVATE_H_ -#define _LIBMAPLE_I2C_PRIVATE_H_ - -#include - -/* For old-style definitions (SDA/SCL on same GPIO device) */ -#define I2C_DEV_OLD(num, port, sda, scl) \ - { \ - .regs = I2C##num##_BASE, \ - .gpio_port = port, \ - .scl_port = NULL, \ - .sda_port = NULL, \ - .sda_pin = sda, \ - .scl_pin = scl, \ - .clk_id = RCC_I2C##num, \ - .ev_nvic_line = NVIC_I2C##num##_EV, \ - .er_nvic_line = NVIC_I2C##num##_ER, \ - .state = I2C_STATE_DISABLED, \ - } - -/* For new-style definitions (SDA/SCL may be on different GPIO devices) */ -#define I2C_DEV_NEW(num, sdaport, sdabit, sclport, sclbit) \ - { \ - .regs = I2C##num##_BASE, \ - .gpio_port = NULL, \ - .scl_port = sclport, \ - .scl_pin = sclbit, \ - .sda_port = sdaport, \ - .sda_pin = sdabit, \ - .clk_id = RCC_I2C##num, \ - .ev_nvic_line = NVIC_I2C##num##_EV, \ - .er_nvic_line = NVIC_I2C##num##_ER, \ - .state = I2C_STATE_DISABLED, \ - } - -void _i2c_irq_handler(i2c_dev *dev); -void _i2c_irq_error_handler(i2c_dev *dev); - -struct gpio_dev; - -static inline struct gpio_dev* scl_port(const i2c_dev *dev) { - return (dev->gpio_port == NULL) ? dev->scl_port : dev->gpio_port; -} - -static inline struct gpio_dev* sda_port(const i2c_dev *dev) { - return (dev->gpio_port == NULL) ? dev->sda_port : dev->gpio_port; -} - -#endif /* _LIBMAPLE_I2C_PRIVATE_H_ */ diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/adc.h b/STM32F3/cores/maple/libmaple/include/libmaple/adc.h deleted file mode 100644 index e2d711d..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/adc.h +++ /dev/null @@ -1,319 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/adc.h - * @author Marti Bolivar , - * Perry Hung , - * F3-port by Hanspeter Portner - * @brief Analog-to-Digital Conversion (ADC) header. - */ - -#ifndef _LIBMAPLE_ADC_H_ -#define _LIBMAPLE_ADC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include -#include - -/** - * TODO document - */ -typedef struct adc_callback_data { - uint32 irq_flags; - void *arg; -} adc_callback_data; - -/** - * TODO document - */ -typedef struct adc_private_data { - void (*handler)(adc_callback_data*); - uint32 handler_flags; - adc_callback_data cb_data; -} adc_private_data; - -/* Pull in the series header - * - * IMPORTANT: The series header must define the following: - * - * - enum adc_extsel_event (and typedef to adc_extsel_event): One per - * external event used to trigger start of conversion of a regular - * group. If two different series support the same event as a - * trigger, they must use the same token for the enumerator for that - * event. (The value of the enumerator is of course allowed to be - * different). - * - * - enum adc_smp_rate (and typedef to adc_smp_rate): One per - * available sampling time. These must be in the form ADC_SMPR_X_Y - * for X.Y cycles (e.g. ADC_SMPR_1_5 means 1.5 cycles), or - * ADC_SMPR_X for X cycles (e.g. ADC_SMPR_3 means 3 cycles). - * - * - enum adc_prescaler (and typedef): One per available prescaler, - * suitable for adc_set_prescaler. Series which have the same - * prescaler dividers (e.g. STM32F1 and STM32F2 both divide PCLK2 by - * 2, 4, 6, or 8) must provide the same tokens as enumerators, for - * portability. - */ - -#include - -/* - * Routines - */ - -extern void adc_init(const adc_dev *dev); - -/** - * @brief Set external event select for regular group - * @param dev ADC device - * @param event Event used to trigger the start of conversion. - * @see adc_extsel_event - */ -extern void adc_set_extsel(const adc_dev *dev, adc_extsel_event event); - -/** - * @brief Set the sample rate for all channels on an ADC device. - * - * Don't call this during conversion. - * - * @param dev adc device - * @param smp_rate sample rate to set - * @see adc_smp_rate - */ -extern void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate); - -/** - * @brief Enable scan mode for an ADC. - * - * In scan mode, the ADC converts all channels in a regular or - * injected sequence. After each conversion is done, the ADC - * automatically starts converting the next channel in the sequence. - * - * Scan mode is disabled by default. - * - * @see adc_disable_scan() - */ -extern void adc_enable_scan(const adc_dev *dev); - -/** - * @brief Disable scan mode for an ADC. - * - * This is the default setting. - * - * @see adc_enable_scan() - */ -extern void adc_disable_scan(const adc_dev *dev); - -/** - * @brief Enable continuous mode for an ADC. - * - * In this mode, the ADC will automatically perform conversions - * continuously until taken out of this mode or disabled. - * - * Continuous mode is disabled by default. - * - * @see adc_disable_continuous() - */ -extern void adc_enable_continuous(const adc_dev *dev); - -/** - * @brief Disable continuous mode for an ADC. - * - * This is the default setting. - * - * @see adc_enable_continuous() - */ -extern void adc_disable_continuous(const adc_dev *dev); - -/** - * @brief Set the sequence of channels to convert. - * - * This sets the (regular) sequence of up to 16 channels to convert. - * - * @param dev ADC device - * @param channels ADC channels to convert; these can repeat and may - * be in any order. - * @param len Length of `channels', from 1 to 16. - * @see adc_start_conv() - */ -extern void adc_set_conv_seq(const adc_dev *dev, const uint8 *channels, uint8 len); - -/** - * @brief Attach an interrupt handler and enable its interrupts. - * - * This function sets `handler' as the function to be called when any - * ADC interrupts for `dev' occur. At most one ADC interrupt handler - * may be attached at any time. Subsequent calls to this function will - * overwrite any previously attached handler. - * - * When `handler' is called, its argument will point to a struct - * adc_callback_data. The .irq_flags field in this struct will be a - * logical OR of adc_interrupt_id values encoding the reason(s) for - * the call. Its .arg field will be the `arg' argument to this - * function. - * - * The interrupt bits set in the adc_callback_data's .irq_flags will - * always be a subset of those set in the `interrupt_flags' argument - * to this function. That is, interrupts not given here in the - * `interrupt_flags' argument will never cause `handler' to be - * called. This has the effect that any enabled ADC interrupts not - * specified in `interrupt_flags' will be ignored. - * - * This function additionally enables the ADC interrupts specified by - * `interrupt_flags'. - * - * @param dev ADC device whose interrupts to attach to. - * @param interrupt_flags Logical or of adc_interrupt_id values - * specifying interrupts to enable. - * @param handler Interrupt handler to call when any interrupt in - * interrupt_flags occurs. - * @param arg Value to store in .arg field of handler's callback data. - * @see enum adc_interrupt_id - * @see struct adc_callback_data - */ -extern void adc_attach_interrupt(const adc_dev *dev, uint32 interrupt_flags, - void (*handler)(adc_callback_data*), void *arg); - -/** - * @brief Disable ADC interrupts and detach interrupt handlers. - * - * This function disables all interrupts for `dev', and unsets any - * handler attached with adc_attach_interrupt(). - * - * @param dev ADC device whose handler to detach. - */ -extern void adc_detach_interrupt(const adc_dev *dev); - -/** - * @brief Enable ADC interrupts - * @param dev ADC device - * @param interrupt_flags Logical or of adc_interrupt_id values to enable. - * @see adc_disable_interrupt() - * @see adc_attach_interrupt() - */ -extern void adc_enable_interrupts(const adc_dev *dev, uint32 interrupt_flags); - -/** - * @brief Disable ADC interrupts. - * @param dev ADC device - * @param interrupt_flags Logical or of adc_interrupt_id values to disable. - * @brief adc_enable_interrupt() - */ -extern void adc_disable_interrupts(const adc_dev *dev, uint32 interrupt_flags); - -/** - * @brief Perform a single synchronous software triggered conversion on a - * channel. - * @param dev ADC device to use for reading. - * @param channel channel to convert - * @return conversion result - */ -extern uint16 adc_read(const adc_dev *dev, uint8 channel); - -/** - * @brief Set the ADC prescaler. - * - * This determines the ADC clock for all devices. - */ -extern void adc_set_prescaler(adc_prescaler pre); - -/** - * @brief Call a function on all ADC devices. - * @param fn Function to call on each ADC device. - */ -extern void adc_foreach(void (*fn)(const adc_dev*)); - -struct gpio_dev; -/** - * @brief Configure a GPIO pin for ADC conversion. - * @param dev ADC device to use for conversion (currently ignored on - * all targets). - * @param gdev GPIO device to configure. - * @param bit Bit on gdev to configure for ADC conversion. - */ -extern void adc_config_gpio(const struct adc_dev *dev, - struct gpio_dev *gdev, - uint8 bit); - -/** - * @brief Enable an ADC and configure it for single conversion mode. - * - * This function performs any initialization necessary to allow the - * ADC device to perform a single synchronous regular software - * triggered conversion, using adc_read(). - * - * @param dev Device to enable. - * @see adc_read() - */ -extern void adc_enable_single_swstart(const adc_dev* dev); - -/** - * @brief Set the regular channel sequence length. - * - * Defines the total number of conversions in the regular channel - * conversion sequence. - * - * @param dev ADC device. - * @param length Regular channel sequence length, from 1 to 16. - */ -extern void adc_set_reg_seqlen(const adc_dev *dev, uint8 length); - -/** - * @brief Enable an adc peripheral - * @param dev ADC device to enable - */ -extern void adc_enable(const adc_dev *dev); - -/** - * @brief Disable an ADC peripheral - * @param dev ADC device to disable - */ -extern void adc_disable(const adc_dev *dev); - -/** - * @brief Disable all ADC peripherals. - */ -static inline void adc_disable_all(void) { - adc_foreach(adc_disable); -} - -/* - * private - */ -extern void _adc_enable_dev_irq(const adc_dev *dev); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/bitband.h b/STM32F3/cores/maple/libmaple/include/libmaple/bitband.h deleted file mode 100644 index 6e77991..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/bitband.h +++ /dev/null @@ -1,128 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/bitband.h - * - * @brief Bit-banding utility functions - */ - -#ifndef _LIBMAPLE_BITBAND_H_ -#define _LIBMAPLE_BITBAND_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define BB_SRAM_REF 0x20000000 -#define BB_SRAM_BASE 0x22000000 -#define BB_PERI_REF 0x40000000 -#define BB_PERI_BASE 0x42000000 - -static inline volatile uint32* __bb_addr(volatile void*, - uint32, - uint32, - uint32); - -/** - * @brief Obtain a pointer to the bit-band address corresponding to a - * bit in a volatile SRAM address. - * @param address Address in the bit-banded SRAM region - * @param bit Bit in address to bit-band - */ -static inline volatile uint32* bb_sramp(volatile void *address, uint32 bit) { - return __bb_addr(address, bit, BB_SRAM_BASE, BB_SRAM_REF); -} - -/** - * @brief Get a bit from an address in the SRAM bit-band region. - * @param address Address in the SRAM bit-band region to read from - * @param bit Bit in address to read - * @return bit's value in address. - */ -static inline uint8 bb_sram_get_bit(volatile void *address, uint32 bit) { - return *bb_sramp(address, bit); -} - -/** - * @brief Set a bit in an address in the SRAM bit-band region. - * @param address Address in the SRAM bit-band region to write to - * @param bit Bit in address to write to - * @param val Value to write for bit, either 0 or 1. - */ -static inline void bb_sram_set_bit(volatile void *address, - uint32 bit, - uint8 val) { - *bb_sramp(address, bit) = val; -} - -/** - * @brief Obtain a pointer to the bit-band address corresponding to a - * bit in a peripheral address. - * @param address Address in the bit-banded peripheral region - * @param bit Bit in address to bit-band - */ -static inline volatile uint32* bb_perip(volatile void *address, uint32 bit) { - return __bb_addr(address, bit, BB_PERI_BASE, BB_PERI_REF); -} - -/** - * @brief Get a bit from an address in the peripheral bit-band region. - * @param address Address in the peripheral bit-band region to read from - * @param bit Bit in address to read - * @return bit's value in address. - */ -static inline uint8 bb_peri_get_bit(volatile void *address, uint32 bit) { - return *bb_perip(address, bit); -} - -/** - * @brief Set a bit in an address in the peripheral bit-band region. - * @param address Address in the peripheral bit-band region to write to - * @param bit Bit in address to write to - * @param val Value to write for bit, either 0 or 1. - */ -static inline void bb_peri_set_bit(volatile void *address, - uint32 bit, - uint8 val) { - *bb_perip(address, bit) = val; -} - -static inline volatile uint32* __bb_addr(volatile void *address, - uint32 bit, - uint32 bb_base, - uint32 bb_ref) { - return (volatile uint32*)(bb_base + ((uint32)address - bb_ref) * 32 + - bit * 4); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/bkp.h b/STM32F3/cores/maple/libmaple/include/libmaple/bkp.h deleted file mode 100644 index 7e795dd..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/bkp.h +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/bkp.h - * @author F3-port by Hanspeter Portner - * @brief Backup register support (STM32F1 & STM32F3 only). - */ - -#ifndef _LIBMAPLE_BKP_H_ -#define _LIBMAPLE_BKP_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -/** Backup peripheral device type. */ -typedef struct bkp_dev { - bkp_reg_map *regs; /**< Register map */ -} bkp_dev; - -extern const struct bkp_dev *BKP; - -/* - * this function needs to be implemented for each series separately - */ -extern inline __io uint32* bkp_data_register(uint8 reg); - -/** - * @brief Initialize backup interface. - * - * Enables the power and backup interface clocks, and resets the - * backup device. - */ -void bkp_init(void); - -/** - * Enable write access to the backup registers. Backup interface must - * be initialized for subsequent register writes to work. - * @see bkp_init() - */ -void bkp_enable_writes(void); - -/** - * Disable write access to the backup registers. - */ -void bkp_disable_writes(void); - -/** - * Read a value from given backup data register. - * @param reg Data register to read, from 1 to BKP_NR_DATA_REGS (10 on - * medium-density devices, 42 on high-density devices). - */ -uint16 bkp_read(uint8 reg); - -/** - * @brief Write a value to given data register. - * - * Write access to backup registers must be enabled. - * - * @param reg Data register to write, from 1 to BKP_NR_DATA_REGS (10 - * on medium-density devices, 42 on high-density devices). - * @param val Value to write into the register. - * @see bkp_enable_writes() - */ -void bkp_write(uint8 reg, uint16 val); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/comp.h b/STM32F3/cores/maple/libmaple/include/libmaple/comp.h deleted file mode 100644 index 508ba63..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/comp.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/include/libmaple/fpu.h - * @author F3-port by Hanspeter Portner - * @brief Floating Point Unit (COMP) interace. - */ - -#ifndef _LIBMAPLE_COMP_H_ -#define _LIBMAPLE_COMP_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/dac.h b/STM32F3/cores/maple/libmaple/include/libmaple/dac.h deleted file mode 100644 index 56bfdc4..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/dac.h +++ /dev/null @@ -1,158 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2010 Bryan Newbold. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/dac.h - * @brief Digital to analog converter support. - */ - -/* See notes/dac.txt for more info */ - -#ifndef _LIBMAPLE_DAC_H_ -#define _LIBMAPLE_DAC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include -#include -#include - -/* - * Register map base and device pointers. - * - * The DACs are the same on all supported targets, so it's not worth - * repeating these in the series headers. - */ - -#define DAC_BASE ((struct dac_reg_map*)0x40007400) - -/** DAC device type. */ -typedef struct dac_dev { - dac_reg_map *regs; /**< Register map */ -} dac_dev; - -#if STM32_HAVE_DAC -extern const dac_dev *DAC; -#endif - -/* - * Register bit definitions - */ - -/* Control register */ - -/* Channel 1 control */ -#define DAC_CR_EN1 (1U << 0) /* Enable */ -#define DAC_CR_BOFF1 (1U << 1) /* Output buffer disable */ -#define DAC_CR_TEN1 (1U << 2) /* Trigger enable */ -#define DAC_CR_TSEL1 (0x7 << 3) /* Trigger selection */ -#define DAC_CR_WAVE1 (0x3 << 6) /* Noise/triangle wave */ -#define DAC_CR_MAMP1 (0xF << 8) /* Mask/amplitude selector */ -#define DAC_CR_DMAEN1 (1U << 12) /* DMA enable */ -/* Channel 2 control */ -#define DAC_CR_EN2 (1U << 16) /* Enable */ -#define DAC_CR_BOFF2 (1U << 17) /* Output buffer disable */ -#define DAC_CR_TEN2 (1U << 18) /* Trigger enable */ -#define DAC_CR_TSEL2 (0x7 << 19) /* Trigger selection */ -#define DAC_CR_WAVE2 (0x3 << 22) /* Noise/triangle wave */ -#define DAC_CR_MAMP2 (0xF << 24) /* Mask/amplitude selector */ -#define DAC_CR_DMAEN2 (1U << 28) /* DMA enable */ - -/* Software trigger register */ - -#define DAC_SWTRIGR_SWTRIG1 (1U << 0) /* Channel 1 software trigger */ -#define DAC_SWTRIGR_SWTRIG2 (1U << 1) /* Channel 2 software trigger */ - -/* Channel 1 12-bit right-aligned data holding register */ - -#define DAC_DHR12R1_DACC1DHR 0x00000FFF - -/* Channel 1 12-bit left-aligned data holding register */ - -#define DAC_DHR12L1_DACC1DHR 0x0000FFF0 - -/* Channel 1 8-bit left-aligned data holding register */ - -#define DAC_DHR8R1_DACC1DHR 0x000000FF - -/* Channel 2 12-bit right-aligned data holding register */ - -#define DAC_DHR12R2_DACC2DHR 0x00000FFF - -/* Channel 2 12-bit left-aligned data holding register */ - -#define DAC_DHR12L2_DACC2DHR 0x0000FFF0 - -/* Channel 2 8-bit left-aligned data holding register */ - -#define DAC_DHR8R2_DACC2DHR 0x000000FF - -/* Dual DAC 12-bit right-aligned data holding register */ - -#define DAC_DHR12RD_DACC1DHR 0x00000FFF -#define DAC_DHR12RD_DACC2DHR 0x0FFF0000 - -/* Dual DAC 12-bit left-aligned data holding register */ - -#define DAC_DHR12LD_DACC1DHR 0x0000FFF0 -#define DAC_DHR12LD_DACC2DHR 0xFFF00000 - -/* Dual DAC 8-bit left-aligned data holding register */ - -#define DAC_DHR8RD_DACC1DHR 0x000000FF -#define DAC_DHR8RD_DACC2DHR 0x0000FF00 - -/* Channel 1 data output register */ - -#define DAC_DOR1_DACC1DOR 0x00000FFF - -/* Channel 1 data output register */ - -#define DAC_DOR2_DACC2DOR 0x00000FFF - -/* - * Routines - */ - -/* We take the dev argument in these for future-proofing */ - -#define DAC_CH1 0x1 -#define DAC_CH2 0x2 -void dac_init(const dac_dev *dev, uint32 flags); - -void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val); -void dac_enable_channel(const dac_dev *dev, uint8 channel); -void dac_disable_channel(const dac_dev *dev, uint8 channel); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/dma.h b/STM32F3/cores/maple/libmaple/include/libmaple/dma.h deleted file mode 100644 index e22cdaf..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/dma.h +++ /dev/null @@ -1,444 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/dma.h - * - * @author Marti Bolivar ; - * Original implementation by Michael Hope - * - * @brief Direct Memory Access peripheral support - */ - -#ifndef _LIBMAPLE_DMA_H_ -#define _LIBMAPLE_DMA_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* provides: - * - * - An opaque dma_tube type, and predefined rvalues for each tube - * supported by the series. - * - * A "DMA tube" is a series-specific (hopefully integer) datatype - * that abstracts the conduit through which DMA-ed data flow. - * - * Examples: On STM32F1, dma_tube is just an alias for dma_channel, - * and the tube values are just DMA_CH1 (=1), DMA_CH2 (=2), etc. - * - * Note that a dma_tube doesn't have to be an enum, and its values - * don't have to be integral. They _do_ need to be cheap to pass as - * arguments, though. - * - * - struct dma_tube_reg_map (and typedef to dma_tube_reg_map). DMA - * register maps tend to be split into global registers and per-tube - * registers. It's convenient to pass around pointers to a tube's - * registers, since that makes it possible to configure or otherwise - * mess with a tube without knowing which one you're dealing with. - * - * - Base pointers to the various dma_tube_reg_maps. - * - * Examples: On STM32F1, these are DMAxCHy_BASE. You can access - * registers like DMAxCHy_BASE->CPAR, etc. - * - * - enum dma_request_src (and typedef to dma_request_src). This - * specifies the peripheral DMA request sources (e.g. USART TX DMA - * requests, etc.). - * - * - enum dma_mode_flags (and typedef to dma_mode_flags). Used in - * dma_tube_config. If two series both support the same mode flags, - * they must use the same enumerator names for those flags (the - * values of those enumerators are of course allowed to differ). - * - * - Normal stuff: dma_reg_map and base pointers, register bit - * definitions, dma_dev pointer declarations, and any other - * convenience functions useful for the series. */ -#include -/* buys us dma_dev and other necessities. */ -#include -#include - -/* - * Declarations/documentation for some of the series-provided types. - */ - -/** - * @brief (Series-dependent) DMA request sources. - * - * These specify the various pieces of peripheral functionality which - * may make DMA requests. Use them to set up a DMA transfer (see - * struct dma_tube_config, dma_tube_cfg()). - */ -enum dma_request_src; - -/** - * @brief (Series-dependent) DMA tube configuration flags. - * These specify miscellaneous bits of configuration for a DMA tube. - * @see struct dma_mode_config - */ -enum dma_cfg_flags; - -/** - * @brief (Series-dependent) DMA tube register map type. - * This allows you to access a tube's registers as a group. - * @see dma_tube_regs() - */ -struct dma_tube_reg_map; - -/* - * Convenience functions - */ - -/* Initialization */ - -void dma_init(dma_dev *dev); - -/* dma_tube configuration - * - * Use these types and functions to set up DMA transfers, handle - * interrupts, etc. The main function of interest is dma_tube_cfg(), - * which the various series implement separately. */ - -/** - * @brief Specifies a DMA tube configuration. - * - * Use one of these to set up a DMA transfer by passing it to - * dma_tube_cfg(). - * - * @see dma_tube_cfg() - * @see dma_xfer_size - */ -typedef struct dma_tube_config { - /** Source of data */ - __io void *tube_src; - /** Source transfer size */ - dma_xfer_size tube_src_size; - - /** Destination of data */ - __io void *tube_dst; - /** Destination transfer size */ - dma_xfer_size tube_dst_size; - - /** - * Number of data to transfer (0 to 65,535). - * - * Note that this is NOT measured in bytes; it's measured in - * number of data, which occur in multiples of tube_src_size. For - * example, if tube_src_size is DMA_SIZE_32BITS and tube_nr_xfers - * is 2, then 8 total bytes will be transferred. - */ - unsigned tube_nr_xfers; - - /** - * Target-specific configuration flags. - * - * These are an OR of series-specific enum dma_mode_flags values. - * Consult the documentation for your target for what flags you - * can use here. - * - * Typical flag examples: DMA_CFG_SRC_INC, DMA_CFG_DST_INC, - * DMA_CFG_CIRC, DMA_CFG_CMPLT_IE, etc. - */ - unsigned tube_flags; - - /** - * Currently unused. You must set this to 0 or something valid for - * your target. */ - void *target_data; - - /** - * Hardware DMA request source. - * - * This is ignored for memory-to-memory transfers. - */ - enum dma_request_src tube_req_src; -} dma_tube_config; - -#define DMA_TUBE_CFG_SUCCESS 0 -#define DMA_TUBE_CFG_EREQ 1 -#define DMA_TUBE_CFG_ENDATA 2 -#define DMA_TUBE_CFG_EDEV 3 -#define DMA_TUBE_CFG_ESRC 4 -#define DMA_TUBE_CFG_EDST 5 -#define DMA_TUBE_CFG_EDIR 6 -#define DMA_TUBE_CFG_ESIZE 7 -#define DMA_TUBE_CFG_ECFG 0xFF -/** - * @brief Configure a DMA tube. - * - * Use this function to set up a DMA transfer. The tube will be - * disabled before being reconfigured. The transfer will have low - * priority by default. You can choose another priority before the - * transfer begins using dma_set_priority(). You can manage your - * interrupt handlers for the tube using dma_attach_interrupt() and - * dma_detach_interrupt(). - * - * After calling dma_tube_cfg() and performing any other desired - * configuration, start the transfer using dma_enable(). - * - * @param dev DMA device. - * @param tube DMA tube to configure. - * @param cfg Configuration to apply to tube. - * - * @return DMA_TUBE_CFG_SUCCESS (0) on success, <0 on failure. On - * failure, returned value will be the opposite (-) of one of: - * - * - DMA_TUBE_CFG_EREQ: tube doesn't work with cfg->tube_req_src - * - DMA_TUBE_CFG_ENDATA: cfg->tube_[src,dst]_size are - * incompatible with cfg->tube_nr_xfers, or cfg->tube_nr_xfers - * is out of bounds. - * - DMA_TUBE_CFG_EDEV: dev does not support cfg - * - DMA_TUBE_CFG_ESRC: bad cfg->tube_src - * - DMA_TUBE_CFG_EDST: bad cfg->tube_dst - * - DMA_TUBE_CFG_EDIR: dev can't transfer from cfg->tube_src to - * cfg->tube_dst - * - DMA_TUBE_CFG_ESIZE: something ended up wrong due to MSIZE/PSIZE - * - DMA_TUBE_CFG_ECFG: generic "something's wrong" - * - * @sideeffect Disables tube. May alter tube's registers even when an - * error occurs. - * @see struct dma_tube_config - * @see dma_attach_interrupt() - * @see dma_detach_interrupt() - * @see dma_enable() - */ -extern int dma_tube_cfg(dma_dev *dev, dma_tube tube, dma_tube_config *cfg); - -/* Other tube configuration functions. You can use these if - * dma_tube_cfg() isn't enough, or to adjust parts of an existing tube - * configuration. */ - -/** DMA transfer priority. */ -typedef enum dma_priority { - DMA_PRIORITY_LOW = 0, /**< Low priority */ - DMA_PRIORITY_MEDIUM = 1, /**< Medium priority */ - DMA_PRIORITY_HIGH = 2, /**< High priority */ - DMA_PRIORITY_VERY_HIGH = 3, /**< Very high priority */ -} dma_priority; - -/** - * @brief Set the priority of a DMA transfer. - * - * You may not call this function while the tube is enabled. - * - * @param dev DMA device - * @param tube DMA tube - * @param priority priority to set. - */ -extern void dma_set_priority(dma_dev *dev, dma_tube tube, - dma_priority priority); - -/** - * @brief Set the number of data transfers on a DMA tube. - * - * You may not call this function while the tube is enabled. - * - * @param dev DMA device - * @param tube Tube through which the transfer will occur. - * @param num_transfers Number of DMA transactions to set. - */ -extern void dma_set_num_transfers(dma_dev *dev, dma_tube tube, - uint16 num_transfers); - -/** - * @brief Set the base memory address where data will be read from or - * written to. - * - * You must not call this function while the tube is enabled. - * - * If the DMA memory size is 16 bits, the address is automatically - * aligned to a half-word. If the DMA memory size is 32 bits, the - * address is aligned to a word. - * - * @param dev DMA Device - * @param tube Tube whose base memory address to set. - * @param address Memory base address to use. - */ -extern void dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *address); - -/** - * @brief Set the base peripheral address where data will be read from - * or written to. - * - * You must not call this function while the channel is enabled. - * - * If the DMA peripheral size is 16 bits, the address is automatically - * aligned to a half-word. If the DMA peripheral size is 32 bits, the - * address is aligned to a word. - * - * @param dev DMA Device - * @param tube Tube whose peripheral data register base address to set. - * @param address Peripheral memory base address to use. - */ -extern void dma_set_per_addr(dma_dev *dev, dma_tube tube, __io void *address); - -/* Interrupt handling */ - -/** - * @brief Attach an interrupt to a DMA transfer. - * - * Interrupts are enabled using series-specific mode flags in - * dma_tube_cfg(). - * - * @param dev DMA device - * @param tube Tube to attach handler to - * @param handler Interrupt handler to call when tube interrupt fires. - * @see dma_tube_cfg() - * @see dma_get_irq_cause() - * @see dma_detach_interrupt() - */ -extern void dma_attach_interrupt(dma_dev *dev, dma_tube tube, - void (*handler)(void)); - - -/** - * @brief Detach a DMA transfer interrupt handler. - * - * After calling this function, the given tube's interrupts will be - * disabled. - * - * @param dev DMA device - * @param tube Tube whose handler to detach - * @sideeffect Clears the tube's interrupt enable bits. - * @see dma_attach_interrupt() - */ -extern void dma_detach_interrupt(dma_dev *dev, dma_tube tube); - -/* Tube enable/disable */ - -/** - * @brief Enable a DMA tube. - * - * If the tube has been properly configured, calling this function - * allows it to start serving DMA requests. - * - * @param dev DMA device - * @param tube Tube to enable - * @see dma_tube_cfg() - */ -extern void dma_enable(dma_dev *dev, dma_tube tube); - -/** - * @brief Disable a DMA channel. - * - * Calling this function makes the tube stop serving DMA requests. - * - * @param dev DMA device - * @param tube Tube to disable - */ -extern void dma_disable(dma_dev *dev, dma_tube tube); - -/** - * @brief Check if a DMA tube is enabled. - * @param dev DMA device. - * @param tube Tube to check. - * @return 0 if the tube is disabled, >0 if it is enabled. - */ -static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube); - -/* Other conveniences */ - -/** - * @brief Obtain a pointer to an individual DMA tube's registers. - * - * Examples: - * - * - On STM32F1, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1. - * - * @param dev DMA device. - * @param tube DMA tube whose register map to obtain. - * @return (Series-specific) tube register map. - */ -static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, dma_tube tube); - -/** - * Encodes the reason why a DMA interrupt was called. - * @see dma_get_irq_cause() - */ -typedef enum dma_irq_cause { - DMA_TRANSFER_COMPLETE, /**< Transfer is complete. */ - DMA_TRANSFER_HALF_COMPLETE, /**< Transfer is half complete. */ - DMA_TRANSFER_ERROR, /**< Error occurred during transfer. */ - DMA_TRANSFER_DME_ERROR, /**< - * @brief Direct mode error occurred during - * transfer. */ - DMA_TRANSFER_FIFO_ERROR, /**< FIFO error occurred during transfer. */ -} dma_irq_cause; - -/** - * @brief Discover the reason why a DMA interrupt was called. - * - * You may only call this function within an attached interrupt - * handler for the given channel. - * - * This function resets the internal DMA register state which encodes - * the cause of the interrupt; consequently, it can only be called - * once per interrupt handler invocation. - * - * @param dev DMA device - * @param tube Tube whose interrupt is being handled. - * @return Reason why the interrupt fired. - * @sideeffect Clears flags in dev's interrupt status registers. - * @see dma_attach_interrupt() - * @see dma_irq_cause - */ -extern dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_tube tube); - -/** - * @brief Get the ISR status bits for a DMA channel. - * - * The bits are returned right-aligned, in the order they appear in - * the corresponding ISR register. - * - * If you're trying to figure out why a DMA interrupt fired, you may - * find dma_get_irq_cause() more convenient. - * - * @param dev DMA device - * @param tube Tube whose ISR bits to return. - * @see dma_get_irq_cause(). - */ -static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube); - -/** - * @brief Clear the ISR status bits for a given DMA tube. - * - * If you're trying to clean up after yourself in a DMA interrupt, you - * may find dma_get_irq_cause() more convenient. - * - * @param dev DMA device - * @param tube Tube whose ISR bits to clear. - * @see dma_get_irq_cause() - */ -static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/dma_common.h b/STM32F3/cores/maple/libmaple/include/libmaple/dma_common.h deleted file mode 100644 index 3765cd5..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/dma_common.h +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/dma_common.h - * @author Marti Bolivar - * @brief Common DMA sub-header for and . - * - * CONTENTS UNSTABLE. The existence of this file is an implementation - * detail. Never include it directly. If you need something from - * here, include instead. - */ - -/* - * There's a fair amount of common DMA functionality needed by each - * and . This header exists in order - * to provide it to both, avoiding some hacks and circular - * dependencies. - */ - -#ifndef _LIBMAPLE_DMA_COMMON_H_ -#define _LIBMAPLE_DMA_COMMON_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include -#include - -/* - * Devices - */ - -struct dma_reg_map; - -/* Encapsulates state related to user interrupt handlers. You - * shouldn't touch these directly; use dma_attach_interrupt() and - * dma_detach_interupt() instead. */ -typedef struct dma_handler_config { - void (*handler)(void); /* User handler */ - nvic_irq_num irq_line; /* IRQ line for interrupt */ -} dma_handler_config; - -/** DMA device type */ -typedef struct dma_dev { - struct dma_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< Clock ID */ - struct dma_handler_config handlers[]; /**< For internal use */ -} dma_dev; - -/** - * @brief DMA channels - * - * Notes: - * - This is also the dma_tube type for STM32F1. - * - Channel 0 is not available on all STM32 series. - * - * @see dma_tube - */ -typedef enum dma_channel { - DMA_CH0 = 0, /**< Channel 0 */ - DMA_CH1 = 1, /**< Channel 1 */ - DMA_CH2 = 2, /**< Channel 2 */ - DMA_CH3 = 3, /**< Channel 3 */ - DMA_CH4 = 4, /**< Channel 4 */ - DMA_CH5 = 5, /**< Channel 5 */ - DMA_CH6 = 6, /**< Channel 6 */ - DMA_CH7 = 7, /**< Channel 7 */ -} dma_channel; - -/** - * @brief Source and destination transfer sizes. - * Use these when initializing a struct dma_tube_config. - * @see struct dma_tube_config - * @see dma_tube_cfg - */ -typedef enum dma_xfer_size { - DMA_SIZE_8BITS = 0, /**< 8-bit transfers */ - DMA_SIZE_16BITS = 1, /**< 16-bit transfers */ - DMA_SIZE_32BITS = 2, /**< 32-bit transfers */ -} dma_xfer_size; - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/dsp.h b/STM32F3/cores/maple/libmaple/include/libmaple/dsp.h deleted file mode 100644 index 435c801..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/dsp.h +++ /dev/null @@ -1,131 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/include/libmaple/dsp.h - * @author F3-port by Hanspeter Portner - * @brief Convenience macros for the digital signal processing (DSP) - * instruction set of the ARM Cortex M4 microcontroller. - */ - -#ifndef _LIBMAPLE_DSP_H_ -#define _LIBMAPLE_DSP_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#define DSP3(ID, A, B, C) \ -({ \ - uint32_t X; \ - asm volatile (ID" %[res], %[val1], %[val2], %[val3]" \ - : [res]"=r" (X) \ - : [val1]"r" (A), [val2]"r" (B), [val3]"r" (C) \ - ); \ - (uint32_t)X; \ -}) - -#define DSP2(ID, A, B) \ -({ \ - uint32_t X; \ - asm volatile (ID" %[res], %[val1], %[val2]" \ - : [res]"=r" (X) \ - : [val1]"r" (A), [val2]"r" (B) \ - );\ - (uint32_t)X; \ -}) - -#define DSP1(ID, A) \ -({ \ - uint32_t X; \ - asm volatile (ID" %[res], %[val1]" \ - : [res]"=r" (X) \ - : [val1]"r" (A) \ - ); \ - (uint32_t)X; \ -}) - -/* General data processing instructions */ -#define __rev16(A) DSP1("REV16", A) -//TODO - -/* Multiply and divide instructions */ -//TODO - -/* Saturating instructions */ -//TODO - -/* Packing and unpacking instructions */ -//TODO - -/* Bitfield instructions */ -//TODO - -/* Floating-point instructions */ -//TODO - -/* Miscellaneous instructions */ -//TODO - -/* SIMD instructions (single instruction multiple data) */ -#define __sadd16(A, B) DSP2("SADD16", A, B) -#define __shadd16(A, B) DSP2("SHADD16", A, B) -#define __ssub16(A, B) DSP2("SSUB16", A, B) -#define __shsub16(A, B) DSP2("SHSUB16", A, B) -#define __uadd16(A, B) DSP2("UADD16", A, B) -#define __uhadd16(A, B) DSP2("UHADD16", A, B) -#define __usub16(A, B) DSP2("USUB16", A, B) -#define __uhsub16(A, B) DSP2("UHSUB16", A, B) - -#define __sadd8(A, B) DSP2("SADD8", A, B) -#define __shadd8(A, B) DSP2("SHADD8", A, B) -#define __ssub8(A, B) DSP2("SSUB8", A, B) -#define __shsub8(A, B) DSP2("SHSUB8", A, B) -#define __uadd8(A, B) DSP2("UADD8", A, B) -#define __uhadd8(A, B) DSP2("UHADD8", A, B) -#define __usub8(A, B) DSP2("USUB8", A, B) -#define __uhsub8(A, B) DSP2("UHSUB8", A, B) - -#define __sasx(A, B) DSP2("SASX", A, B) -#define __ssax(A, B) DSP2("SSAX", A, B) -#define __shasx(A, B) DSP2("SHASX", A, B) -#define __shsax(A, B) DSP2("SHSAX", A, B) -#define __uasx(A, B) DSP2("UASX", A, B) -#define __usax(A, B) DSP2("USAX", A, B) -#define __uhasx(A, B) DSP2("UHASX", A, B) -#define __uhsax(A, B) DSP2("UHSAX", A, B) - -#define __usad8(A, B) DSP2("USAD8", A, B) -#define __usada8(A, B, C) DSP3("USADA8", A, B, C) - -/* MAC instructions (multiply and accumulate) */ -/* TODO */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/exti.h b/STM32F3/cores/maple/libmaple/include/libmaple/exti.h deleted file mode 100644 index 1d201ac..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/exti.h +++ /dev/null @@ -1,143 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/exti.h - * @brief External interrupt control - */ - -/* See notes/exti.txt for more info */ - -#ifndef _LIBMAPLE_EXTI_H_ -#define _LIBMAPLE_EXTI_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include /* provides EXTI_BASE */ -#include - -/* - * Register map and base pointer. - */ - -/** EXTI register map type */ -typedef struct exti_reg_map { - __io uint32 IMR; /**< Interrupt mask register */ - __io uint32 EMR; /**< Event mask register */ - __io uint32 RTSR; /**< Rising trigger selection register */ - __io uint32 FTSR; /**< Falling trigger selection register */ - __io uint32 SWIER; /**< Software interrupt event register */ - __io uint32 PR; /**< Pending register */ -} exti_reg_map; - -/* - * Types: exti_num, exti_cfg, exti_trigger_mode. - * - * A combination of these three specifies an external interrupt - * configuration (see exti_attach_interrupt()). - */ - -/** EXTI line. */ -typedef enum exti_num { - EXTI0, /**< EXTI line 0 */ - EXTI1, /**< EXTI line 1 */ - EXTI2, /**< EXTI line 2 */ - EXTI3, /**< EXTI line 3 */ - EXTI4, /**< EXTI line 4 */ - EXTI5, /**< EXTI line 5 */ - EXTI6, /**< EXTI line 6 */ - EXTI7, /**< EXTI line 7 */ - EXTI8, /**< EXTI line 8 */ - EXTI9, /**< EXTI line 9 */ - EXTI10, /**< EXTI line 10 */ - EXTI11, /**< EXTI line 11 */ - EXTI12, /**< EXTI line 12 */ - EXTI13, /**< EXTI line 13 */ - EXTI14, /**< EXTI line 14 */ - EXTI15, /**< EXTI line 15 */ -} exti_num; - -/** - * @brief EXTI port configuration - * - * These specify which GPIO port an external interrupt line should be - * connected to. - */ -typedef enum exti_cfg { - EXTI_PA, /**< Use PAx pin */ - EXTI_PB, /**< Use PBx pin */ - EXTI_PC, /**< Use PCx pin */ - EXTI_PD, /**< Use PDx pin */ - EXTI_PE, /**< Use PEx pin */ - EXTI_PF, /**< Use PFx pin */ - EXTI_PG, /**< Use PGx pin */ - EXTI_PH, /**< Use PHx pin */ - EXTI_PI, /**< Use PIx pin */ -} exti_cfg; - -/** External interrupt trigger mode */ -typedef enum exti_trigger_mode { - EXTI_RISING, /**< Trigger on the rising edge */ - EXTI_FALLING, /**< Trigger on the falling edge */ - EXTI_RISING_FALLING /**< Trigger on both the rising and falling edges */ -} exti_trigger_mode; - -/* - * Routines - */ - -void exti_attach_interrupt(exti_num num, - exti_cfg port, - voidFuncPtr handler, - exti_trigger_mode mode); -void exti_attach_callback(exti_num num, - exti_cfg port, - voidArgumentFuncPtr handler, - void *arg, - exti_trigger_mode mode); -void exti_detach_interrupt(exti_num num); - -/** - * @brief Set the GPIO port for an EXTI line. - * - * This is a low-level routine that most users will not - * need. exti_attach_interrupt() handles calling this function - * appropriately. - * - * @param num EXTI line - * @param port EXTI configuration for GPIO port to connect to num. - * @see exti_num - * @see exti_cfg - */ -extern void exti_select(exti_num num, exti_cfg port); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/flash.h b/STM32F3/cores/maple/libmaple/include/libmaple/flash.h deleted file mode 100644 index 943e466..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/flash.h +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/flash.h - * @brief Flash support. - */ - -#ifndef _LIBMAPLE_FLASH_H_ -#define _LIBMAPLE_FLASH_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -#define FLASH_WAIT_STATE_0 0x0 -#define FLASH_WAIT_STATE_1 0x1 -#define FLASH_WAIT_STATE_2 0x2 -#define FLASH_WAIT_STATE_3 0x3 -#define FLASH_WAIT_STATE_4 0x4 -#define FLASH_WAIT_STATE_5 0x5 -#define FLASH_WAIT_STATE_6 0x6 -#define FLASH_WAIT_STATE_7 0x7 - -/* The series header must define: - * - * - FLASH_SAFE_WAIT_STATES, the smallest number of wait states that - * it is safe to use when SYSCLK is at its fastest documented rate - * and the MCU is powered at 3.3V (i.e. this doesn't consider - * overclocking or low voltage operation). - * - * - The following bit flags, for flash_enable_features(): - * - * -- FLASH_PREFETCH: prefetcher - * -- FLASH_ICACHE: instruction cache - * -- FLASH_DCACHE: data cache - * - * See that function's Doxygen for more restrictions. - */ -#include - -#ifdef __DOXYGEN__ -/** Flash register map base pointer. */ -#define FLASH_BASE -#endif - -/* - * Flash routines - */ - -void flash_set_latency(uint32 wait_states); - -/** - * @brief Enable Flash memory features - * - * If the target MCU doesn't provide a feature (e.g. instruction and - * data caches on the STM32F1), the flag will be ignored. This allows - * using these flags unconditionally, with the desired effect taking - * place on targets that support them. - * - * @param feature_flags Bitwise OR of the following: - * FLASH_PREFETCH (turns on prefetcher), - * FLASH_ICACHE (turns on instruction cache), - * FLASH_DCACHE (turns on data cache). - */ -static inline void flash_enable_features(uint32 feature_flags) { - FLASH_BASE->ACR |= feature_flags; -} - -/** - * @brief Deprecated. Use flash_enable_features(FLASH_PREFETCH) instead. - */ -static inline void flash_enable_prefetch(void) { - flash_enable_features(FLASH_PREFETCH); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/fpu.h b/STM32F3/cores/maple/libmaple/include/libmaple/fpu.h deleted file mode 100644 index f8e2037..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/fpu.h +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/include/libmaple/fpu.h - * @author F3-port by Hanspeter Portner - * @brief Floating Point Unit (FPU) interace. - */ - -#ifndef _LIBMAPLE_FPU_H_ -#define _LIBMAPLE_FPU_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/** - * @brief Enable floating point unit. - */ -void fpu_enable(void); - -/** - * @brief Disable floating point unit. - */ -void fpu_disable(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/fsmc.h b/STM32F3/cores/maple/libmaple/include/libmaple/fsmc.h deleted file mode 100644 index 6225fee..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/fsmc.h +++ /dev/null @@ -1,340 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Bryan Newbold. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/fsmc.h - * @brief Flexible static memory controller support. - */ - -/* - * See ../notes/fsmc.txt for more info - */ - -#ifndef _LIBMAPLE_FSMC_H_ -#define _LIBMAPLE_FSMC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -#if !STM32_HAVE_FSMC -#error "FSMC is unavailable on your MCU" -#endif - -/* - * Register maps and devices - */ - -/** FSMC register map type */ -typedef struct fsmc_reg_map { - __io uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ - __io uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ - __io uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ - __io uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ - __io uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ - __io uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ - __io uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ - __io uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ - const uint8 RESERVED1[64]; /**< Reserved */ - __io uint32 PCR2; /**< PC Card/NAND Flash control register 2 */ - __io uint32 SR2; /**< FIFO status and interrupt register 2 */ - __io uint32 PMEM2; /**< Common memory space timing register 2 */ - __io uint32 PATT2; /**< Attribute memory space timing register 2 */ - const uint8 RESERVED2[4]; /**< Reserved */ - __io uint32 ECCR2; /**< ECC result register 2 */ - const uint8 RESERVED3[2]; - __io uint32 PCR3; /**< PC Card/NAND Flash control register 3 */ - __io uint32 SR3; /**< FIFO status and interrupt register 3 */ - __io uint32 PMEM3; /**< Common memory space timing register 3 */ - __io uint32 PATT3; /**< Attribute memory space timing register 3 */ - const uint32 RESERVED4; /**< Reserved */ - __io uint32 ECCR3; /**< ECC result register 3 */ - const uint8 RESERVED5[8]; /**< Reserved */ - __io uint32 PCR4; /**< PC Card/NAND Flash control register 4 */ - __io uint32 SR4; /**< FIFO status and interrupt register 4 */ - __io uint32 PMEM4; /**< Common memory space timing register 4 */ - __io uint32 PATT4; /**< Attribute memory space timing register 4 */ - __io uint32 PIO4; /**< I/O space timing register 4 */ - const uint8 RESERVED6[80]; /**< Reserved */ - __io uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ - const uint32 RESERVED7; /**< Reserved */ - __io uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ - const uint32 RESERVED8; /**< Reserved */ - __io uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ - const uint32 RESERVED9; /**< Reserved */ - __io uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ -} __attribute__((packed)) fsmc_reg_map; - -#define __FSMCB 0xA0000000 - -/** FSMC register map base pointer */ -#define FSMC_BASE ((struct fsmc_reg_map*)__FSMCB) - -/** FSMC NOR/PSRAM register map type */ -typedef struct fsmc_nor_psram_reg_map { - __io uint32 BCR; /**< Chip-select control register */ - __io uint32 BTR; /**< Chip-select timing register */ - const uint8 RESERVED[252]; /**< Reserved */ - __io uint32 BWTR; /**< Write timing register */ -} fsmc_nor_psram_reg_map; - -/** FSMC NOR/PSRAM base pointer 1 */ -#define FSMC_NOR_PSRAM1_BASE ((struct fsmc_nor_psram_reg_map*)__FSMCB) - -/** FSMC NOR/PSRAM base pointer 2 */ -#define FSMC_NOR_PSRAM2_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x8)) - -/** FSMC NOR/PSRAM base pointer 3 */ -#define FSMC_NOR_PSRAM3_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x10)) - -/** FSMC NOR/PSRAM base pointer 4 */ -#define FSMC_NOR_PSRAM4_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x18)) - -/* - * Register bit definitions - */ - -/* NOR/PSRAM chip-select control registers */ - -#define FSMC_BCR_CBURSTRW_BIT 19 -#define FSMC_BCR_ASYNCWAIT_BIT 15 -#define FSMC_BCR_EXTMOD_BIT 14 -#define FSMC_BCR_WAITEN_BIT 13 -#define FSMC_BCR_WREN_BIT 12 -#define FSMC_BCR_WAITCFG_BIT 11 -#define FSMC_BCR_WRAPMOD_BIT 10 -#define FSMC_BCR_WAITPOL_BIT 9 -#define FSMC_BCR_BURSTEN_BIT 8 -#define FSMC_BCR_FACCEN_BIT 6 -#define FSMC_BCR_MUXEN_BIT 1 -#define FSMC_BCR_MBKEN_BIT 0 - -#define FSMC_BCR_CBURSTRW (1U << FSMC_BCR_CBURSTRW_BIT) -#define FSMC_BCR_ASYNCWAIT (1U << FSMC_BCR_ASYNCWAIT_BIT) -#define FSMC_BCR_EXTMOD (1U << FSMC_BCR_EXTMOD_BIT) -#define FSMC_BCR_WAITEN (1U << FSMC_BCR_WAITEN_BIT) -#define FSMC_BCR_WREN (1U << FSMC_BCR_WREN_BIT) -#define FSMC_BCR_WAITCFG (1U << FSMC_BCR_WAITCFG_BIT) -#define FSMC_BCR_WRAPMOD (1U << FSMC_BCR_WRAPMOD_BIT) -#define FSMC_BCR_WAITPOL (1U << FSMC_BCR_WAITPOL_BIT) -#define FSMC_BCR_BURSTEN (1U << FSMC_BCR_BURSTEN_BIT) -#define FSMC_BCR_FACCEN (1U << FSMC_BCR_FACCEN_BIT) -#define FSMC_BCR_MWID (0x3 << 4) -#define FSMC_BCR_MWID_8BITS (0x0 << 4) -#define FSMC_BCR_MWID_16BITS (0x1 << 4) -#define FSMC_BCR_MTYP (0x3 << 2) -#define FSMC_BCR_MTYP_SRAM (0x0 << 2) -#define FSMC_BCR_MTYP_PSRAM (0x1 << 2) -#define FSMC_BCR_MTYP_NOR_FLASH (0x2 << 2) -#define FSMC_BCR_MUXEN (1U << FSMC_BCR_MUXEN_BIT) -#define FSMC_BCR_MBKEN (1U << FSMC_BCR_MBKEN_BIT) - -/* SRAM/NOR-Flash chip-select timing registers */ - -#define FSMC_BTR_ACCMOD (0x3 << 28) -#define FSMC_BTR_ACCMOD_A (0x0 << 28) -#define FSMC_BTR_ACCMOD_B (0x1 << 28) -#define FSMC_BTR_ACCMOD_C (0x2 << 28) -#define FSMC_BTR_ACCMOD_D (0x3 << 28) -#define FSMC_BTR_DATLAT (0xF << 24) -#define FSMC_BTR_CLKDIV (0xF << 20) -#define FSMC_BTR_BUSTURN (0xF << 16) -#define FSMC_BTR_DATAST (0xFF << 8) -#define FSMC_BTR_ADDHLD (0xF << 4) -#define FSMC_BTR_ADDSET 0xF - -/* SRAM/NOR-Flash write timing registers */ - -#define FSMC_BWTR_ACCMOD (0x3 << 28) -#define FSMC_BWTR_ACCMOD_A (0x0 << 28) -#define FSMC_BWTR_ACCMOD_B (0x1 << 28) -#define FSMC_BWTR_ACCMOD_C (0x2 << 28) -#define FSMC_BWTR_ACCMOD_D (0x3 << 28) -#define FSMC_BWTR_DATLAT (0xF << 24) -#define FSMC_BWTR_CLKDIV (0xF << 20) -#define FSMC_BWTR_DATAST (0xFF << 8) -#define FSMC_BWTR_ADDHLD (0xF << 4) -#define FSMC_BWTR_ADDSET 0xF - -/* NAND Flash/PC Card controller registers */ - -#define FSMC_PCR_ECCEN_BIT 6 -#define FSMC_PCR_PTYP_BIT 3 -#define FSMC_PCR_PBKEN_BIT 2 -#define FSMC_PCR_PWAITEN_BIT 1 - -#define FSMC_PCR_ECCPS (0x7 << 17) -#define FSMC_PCR_ECCPS_256B (0x0 << 17) -#define FSMC_PCR_ECCPS_512B (0x1 << 17) -#define FSMC_PCR_ECCPS_1024B (0x2 << 17) -#define FSMC_PCR_ECCPS_2048B (0x3 << 17) -#define FSMC_PCR_ECCPS_4096B (0x4 << 17) -#define FSMC_PCR_ECCPS_8192B (0x5 << 17) -#define FSMC_PCR_TAR (0xF << 13) -#define FSMC_PCR_TCLR (0xF << 9) -#define FSMC_PCR_ECCEN (1U << FSMC_PCR_ECCEN_BIT) -#define FSMC_PCR_PWID (0x3 << 4) -#define FSMC_PCR_PWID_8BITS (0x0 << 4) -#define FSMC_PCR_PWID_16BITS (0x1 << 4) -#define FSMC_PCR_PTYP (1U << FSMC_PCR_PTYP_BIT) -#define FSMC_PCR_PTYP_PC_CF_PCMCIA (0x0 << FSMC_PCR_PTYP_BIT) -#define FSMC_PCR_PTYP_NAND (0x1 << FSMC_PCR_PTYP_BIT) -#define FSMC_PCR_PBKEN (1U << FSMC_PCR_PBKEN_BIT) -#define FSMC_PCR_PWAITEN (1U << FSMC_PCR_PWAITEN_BIT) - -/* FIFO status and interrupt registers */ - -#define FSMC_SR_FEMPT_BIT 6 -#define FSMC_SR_IFEN_BIT 5 -#define FSMC_SR_ILEN_BIT 4 -#define FSMC_SR_IREN_BIT 3 -#define FSMC_SR_IFS_BIT 2 -#define FSMC_SR_ILS_BIT 1 -#define FSMC_SR_IRS_BIT 0 - -#define FSMC_SR_FEMPT (1U << FSMC_SR_FEMPT_BIT) -#define FSMC_SR_IFEN (1U << FSMC_SR_IFEN_BIT) -#define FSMC_SR_ILEN (1U << FSMC_SR_ILEN_BIT) -#define FSMC_SR_IREN (1U << FSMC_SR_IREN_BIT) -#define FSMC_SR_IFS (1U << FSMC_SR_IFS_BIT) -#define FSMC_SR_ILS (1U << FSMC_SR_ILS_BIT) -#define FSMC_SR_IRS (1U << FSMC_SR_IRS_BIT) - -/* Common memory space timing registers */ - -#define FSMC_PMEM_MEMHIZ (0xFF << 24) -#define FSMC_PMEM_MEMHOLD (0xFF << 16) -#define FSMC_PMEM_MEMWAIT (0xFF << 8) -#define FSMC_PMEM_MEMSET 0xFF - -/* Attribute memory space timing registers */ - -#define FSMC_PATT_ATTHIZ (0xFF << 24) -#define FSMC_PATT_ATTHOLD (0xFF << 16) -#define FSMC_PATT_ATTWAIT (0xFF << 8) -#define FSMC_PATT_ATTSET 0xFF - -/* I/O space timing register 4 */ - -#define FSMC_PIO_IOHIZ (0xFF << 24) -#define FSMC_PIO_IOHOLD (0xFF << 16) -#define FSMC_PIO_IOWAIT (0xFF << 8) -#define FSMC_PIO_IOSET 0xFF - -/* - * Memory bank boundary addresses - */ - -/** - * @brief Void pointer to base address of FSMC memory bank 1 (NOR/PSRAM). - * - * This bank is split into 4 regions. Each region supports interfacing - * with 1 NOR Flash, SRAM, or PSRAM chip. The base addresses of these - * regions are FSMC_NOR_PSRAM_REGIONx, for x = 1, 2, 3, 4. - */ -#define FSMC_BANK1 ((void*)0x60000000) - -/** - * @brief Void pointer to base address of FSMC memory bank 1, region 1 - * (NOR/PSRAM). - */ -#define FSMC_NOR_PSRAM_REGION1 FSMC_BANK1 - -/** - * @brief Void pointer to base address of FSMC memory bank 1, region 2 - * (NOR/PSRAM). - */ -#define FSMC_NOR_PSRAM_REGION2 ((void*)0x64000000) - -/** - * @brief Void pointer to base address of FSMC memory bank 1, region 3 - * (NOR/PSRAM). - */ -#define FSMC_NOR_PSRAM_REGION3 ((void*)0x68000000) - -/** - * @brief Void pointer to base address of FSMC memory bank 1, region 4 - * (NOR/PSRAM). - */ -#define FSMC_NOR_PSRAM_REGION4 ((void*)0x6C000000) - -/** Void pointer to base address of FSMC memory bank 2 (NAND Flash). */ -#define FSMC_BANK2 ((void*)0x70000000) - -/** Void pointer to base address of FSMC memory bank 3 (NAND Flash). */ -#define FSMC_BANK3 ((void*)0x80000000) - -/** - * @brief Void pointer to base address of FSMC memory bank 4 (PC card - * devices). - */ -#define FSMC_BANK4 ((void*)0x90000000) - -/* - * SRAM/NOR Flash routines - */ - -/** - * @brief Configure FSMC GPIOs for use with SRAM. - */ -void fsmc_sram_init_gpios(void); - -/** - * Set the DATAST bits in the given NOR/PSRAM register map's - * chip-select timing register (FSMC_BTR). - * - * @param regs NOR Flash/PSRAM register map whose chip-select timing - * register to set. - * @param datast Value to use for DATAST bits. - */ -static inline void fsmc_nor_psram_set_datast(fsmc_nor_psram_reg_map *regs, - uint8 datast) { - regs->BTR &= ~FSMC_BTR_DATAST; - regs->BTR |= datast << 8; -} - -/** - * Set the ADDHLD bits in the given NOR/PSRAM register map's chip - * select timing register (FSMC_BTRx). - * - * @param regs NOR Flash/PSRAM register map whose chip-select timing - * register to set. - * @param addset Value to use for ADDSET bits. - */ -static inline void fsmc_nor_psram_set_addset(fsmc_nor_psram_reg_map *regs, - uint8 addset) { - regs->BTR &= ~FSMC_BTR_ADDSET; - regs->BTR |= addset & 0xF; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/gpio.h b/STM32F3/cores/maple/libmaple/include/libmaple/gpio.h deleted file mode 100644 index 0cc3746..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/gpio.h +++ /dev/null @@ -1,121 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/include/libmaple/gpio.h - * @brief General Purpose I/O (GPIO) interace. - */ - -#ifndef _LIBMAPLE_GPIO_H_ -#define _LIBMAPLE_GPIO_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - * Note: Series header must define: - * - enum gpio_pin_mode (TODO think harder about portability here) - */ -#include -#include -#include -#include - -/* - * Device type - */ - -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - /** - * @brief (Deprecated) External interrupt port. - * Instead of dev->exti_port, use gpio_exti_port(dev). - */ - exti_cfg exti_port; -} gpio_dev; - -/* - * Portable routines - */ - -void gpio_init(gpio_dev *dev); -void gpio_init_all(void); -/* TODO flags argument version? */ -void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); - -/** - * @brief Get a GPIO port's corresponding EXTI port configuration. - * @param dev GPIO port whose exti_cfg to return. - */ -static inline exti_cfg gpio_exti_port(gpio_dev *dev) { - return (exti_cfg)(EXTI_PA + (dev->clk_id - RCC_GPIOA)); -} - -/** - * Set or reset a GPIO pin. - * - * Pin must have previously been configured to output mode. - * - * @param dev GPIO device whose pin to set. - * @param pin Pin on to set or reset - * @param val If true, set the pin. If false, reset the pin. - */ -static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { - val = !val; /* "set" bits are lower than "reset" bits */ - dev->regs->BSRR = (1U << pin) << (16 * val); -} - -/** - * Determine whether or not a GPIO pin is set. - * - * Pin must have previously been configured to input mode. - * - * @param dev GPIO device whose pin to test. - * @param pin Pin on dev to test. - * @return True if the pin is set, false otherwise. - */ -static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { - return dev->regs->IDR & (1U << pin); -} - -/** - * Toggle a pin configured as output push-pull. - * @param dev GPIO device. - * @param pin Pin on dev to toggle. - */ -static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { - dev->regs->ODR = dev->regs->ODR ^ (1U << pin); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/i2c.h b/STM32F3/cores/maple/libmaple/include/libmaple/i2c.h deleted file mode 100644 index 8452c2a..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/i2c.h +++ /dev/null @@ -1,304 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/i2c.h - * @author F3-port by Hanspeter Portner - * @brief Inter-Integrated Circuit (I2C) peripheral support - * - * Currently master-only. Usage notes: - * - * - Enable an I2C device with i2c_master_enable(). - * - Initialize an array of struct i2c_msg to suit the bus - * transactions (reads/writes) you wish to perform. - * - Call i2c_master_xfer() to do the work. - */ - -#ifndef _LIBMAPLE_I2C_H_ -#define _LIBMAPLE_I2C_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Series header must provide: - * - * - uint32 _i2c_bus_clk(i2c_dev*): Clock frequency of dev's bus, in - * MHz. (This is for internal use only). - * - * - (optional) _I2C_HAVE_IRQ_FIXUP: Leave undefined, or define to 1. - * This is for internal use only. It's a hack to work around a - * silicon bug related to I2C IRQ pre-emption on some targets. If 1, - * the series header must also declare and implement a routine with - * this signature (it may also be provided as a macro): - * - * void _i2c_irq_priority_fixup(i2c_dev*) - * - * This will be called by i2c_enable_irq() before actually enabling - * I2C interrupts. - * - * - Reg. map base pointers, device pointer declarations. - */ - -#include -#include - -#include -#include -#include -#include - -/** - * @brief I2C message type - */ -typedef struct i2c_msg { - uint16 addr; /**< Address */ - -#define I2C_MSG_READ 0x1 -#define I2C_MSG_10BIT_ADDR 0x2 - /** - * Bitwise OR of: - * - I2C_MSG_READ (write is default) - * - I2C_MSG_10BIT_ADDR (7-bit is default) */ - uint16 flags; - - uint16 length; /**< Message length */ - uint16 xferred; /**< Messages transferred */ - uint8 *data; /**< Data */ -} i2c_msg; - -/* I2C enable options */ -#define I2C_FAST_MODE 0x1 // 400 khz -#define I2C_DUTY_16_9 0x2 // 16/9 duty ratio -/* Flag 0x4 is reserved; DO NOT USE. */ -#define I2C_BUS_RESET 0x8 // Perform a bus reset - -/* I2C error flags */ -#define I2C_ERROR_PROTOCOL (-1) -#define I2C_ERROR_TIMEOUT (-2) - -/* Main I2C API */ - -/** - * @brief Disable an I2C device - * - * This function disables the corresponding peripheral and marks dev's - * state as I2C_STATE_DISABLED. - * - * @param dev Device to disable. - */ -static inline void i2c_disable(i2c_dev *dev) { - dev->regs->CR1 &= ~I2C_CR1_PE; - dev->state = I2C_STATE_DISABLED; -} - -/** - * @brief Wait for an I2C event, or time out in case of error. - * @param dev I2C device - * @param state I2C_state state to wait for - * @param timeout Timeout, in milliseconds - * @return 0 if target state is reached, a negative value on error. - */ -extern int32 wait_for_state_change(i2c_dev *dev, - i2c_state state, - uint32 timeout); - -/** - * @brief Reset an I2C bus. - * - * Reset is accomplished by clocking out pulses until any hung slaves - * release SDA and SCL, then generating a START condition, then a STOP - * condition. - * - * @param dev I2C device - */ -extern void i2c_bus_reset(const i2c_dev *dev); - -/** - * @brief Initialize an I2C device as bus master - * @param dev Device to enable - * @param flags Bitwise or of the following I2C options: - * I2C_FAST_MODE: 400 khz operation, - * I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for - * fast mode), - * I2C_BUS_RESET: Reset the bus and clock out any hung slaves on - * initialization, - * I2C_10BIT_ADDRESSING: Enable 10-bit addressing, - * I2C_REMAP: (deprecated, STM32F1 only) Remap I2C1 to SCL/PB8 - * SDA/PB9. - */ -extern void i2c_master_enable(i2c_dev *dev, uint32 flags); - -/** - * @brief Process an i2c transaction. - * - * Transactions are composed of one or more i2c_msg's, and may be read - * or write tranfers. Multiple i2c_msg's will generate a repeated - * start in between messages. - * - * @param dev I2C device - * @param msgs Messages to send/receive - * @param num Number of messages to send/receive - * @param timeout Bus idle timeout in milliseconds before aborting the - * transfer. 0 denotes no timeout. - * @return 0 on success, - * I2C_ERROR_PROTOCOL if there was a protocol error, - * I2C_ERROR_TIMEOUT if the transfer timed out. - */ -extern int32 i2c_master_xfer(i2c_dev *dev, - i2c_msg *msgs, - uint16 num, - uint32 timeout); - -/** - * @brief Fill data register with slave address - * @param dev I2C device - * @param addr Slave address - * @param rw Read/write bit - */ -extern void i2c_send_slave_addr(i2c_dev *dev, uint32 addr, uint32 rw); - -/* Start/stop conditions */ - -/** - * @brief Generate a start condition on the bus. - * @param dev I2C device - */ -extern void i2c_start_condition(i2c_dev *dev); - -/** - * @brief Generate a stop condition on the bus - * @param dev I2C device - */ -extern void i2c_stop_condition(i2c_dev *dev); - -/* IRQ enable/disable */ - -#ifndef _I2C_HAVE_IRQ_FIXUP -/* The series header provides this if _I2C_HAVE_IRQ_FIXUP is defined, - * but we need it either way. */ -#define _i2c_irq_priority_fixup(dev) ((void)0) -#endif - -/** - * @brief Enable one or more I2C interrupts - * @param dev I2C device - * @param irqs Bitwise or of: - * I2C_IRQ_ERROR (error interrupt), - * I2C_IRQ_EVENT (event interrupt), and - * I2C_IRQ_BUFFER (buffer interrupt). - */ -extern void i2c_enable_irq(i2c_dev *dev, uint32 irqs); - -/** - * @brief Disable one or more I2C interrupts - * @param dev I2C device - * @param irqs Bitwise or of: - * I2C_IRQ_ERROR (error interrupt), - * I2C_IRQ_EVENT (event interrupt), and - * I2C_IRQ_BUFFER (buffer interrupt). - */ -extern void i2c_disable_irq(i2c_dev *dev, uint32 irqs); - -/* ACK/NACK */ - -/** - * @brief Enable I2C acknowledgment - * @param dev I2C device - */ -extern void i2c_enable_ack(i2c_dev *dev); - -/** - * @brief Disable I2C acknowledgment - * @param dev I2C device - */ -extern void i2c_disable_ack(i2c_dev *dev); - -/* GPIO control */ - -/** - * @brief Configure device GPIOs. - * - * Configure GPIO bits dev->sda_pin and dev->scl_pin on GPIO device - * dev->gpio_port for use with I2C device dev. - * - * @param dev I2C Device - * @see i2c_release_gpios() - */ -extern void i2c_config_gpios(const i2c_dev *dev); - -/** - * @brief Release GPIOs controlling an I2C bus - * - * Releases the I2C bus controlled by dev as master, and disconnects - * GPIO bits dev->sda_pin and dev->scl_pin on GPIO device - * dev->gpio_port from I2C device dev. - * - * @param dev I2C device - * @see i2c_config_gpios() - */ -extern void i2c_master_release_bus(const i2c_dev *dev); - -/* Miscellaneous low-level routines */ - -/** - * @brief Initialize an I2C device and reset its registers to their - * default values. - * @param dev Device to initialize. - */ -void i2c_init(i2c_dev *dev); - -/** - * @brief Turn on an I2C peripheral - * @param dev Device to enable - */ -static inline void i2c_peripheral_enable(i2c_dev *dev) { - dev->regs->CR1 |= I2C_CR1_PE; -} - -/** - * @brief Turn off an I2C peripheral - * @param dev Device to turn off - */ -static inline void i2c_peripheral_disable(i2c_dev *dev) { - dev->regs->CR1 &= ~I2C_CR1_PE; -} - -/** - * @brief Fill transmit register - * @param dev I2C device - * @param byte Byte to write - */ -extern void i2c_write(i2c_dev *dev, uint8 byte); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/iwdg.h b/STM32F3/cores/maple/libmaple/include/libmaple/iwdg.h deleted file mode 100644 index 3a16c55..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/iwdg.h +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/iwdg.h - * @author Michael Hope, Marti Bolivar - * @brief Independent watchdog support. - * - * To use the independent watchdog, first call iwdg_init() with the - * appropriate prescaler and IWDG counter reload values for your - * application. Afterwards, you must periodically call iwdg_feed() - * before the IWDG counter reaches 0 to reset the counter to its - * reload value. If you do not, the chip will reset. - * - * Once started, the independent watchdog cannot be turned off. - */ - -#ifndef _LIBMAPLE_IWDG_H_ -#define _LIBMAPLE_IWDG_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Register map - */ - -/** Independent watchdog register map type. */ -typedef struct iwdg_reg_map { - __io uint32 KR; /**< Key register. */ - __io uint32 PR; /**< Prescaler register. */ - __io uint32 RLR; /**< Reload register. */ - __io uint32 SR; /**< Status register */ -} iwdg_reg_map; - -/** Independent watchdog base pointer */ -#define IWDG_BASE ((struct iwdg_reg_map*)0x40003000) - -/* - * Register bit definitions - */ - -/* Key register */ - -#define IWDG_KR_UNLOCK 0x5555 -#define IWDG_KR_FEED 0xAAAA -#define IWDG_KR_START 0xCCCC - -/* Prescaler register */ - -#define IWDG_PR_DIV_4 0x0 -#define IWDG_PR_DIV_8 0x1 -#define IWDG_PR_DIV_16 0x2 -#define IWDG_PR_DIV_32 0x3 -#define IWDG_PR_DIV_64 0x4 -#define IWDG_PR_DIV_128 0x5 -#define IWDG_PR_DIV_256 0x6 - -/* Status register */ - -#define IWDG_SR_RVU_BIT 1 -#define IWDG_SR_PVU_BIT 0 - -#define IWDG_SR_RVU (1U << IWDG_SR_RVU_BIT) -#define IWDG_SR_PVU (1U << IWDG_SR_PVU_BIT) - -/** - * @brief Independent watchdog prescalers. - * - * These divide the 40 kHz IWDG clock. - */ -typedef enum iwdg_prescaler { - IWDG_PRE_4 = IWDG_PR_DIV_4, /**< Divide by 4 */ - IWDG_PRE_8 = IWDG_PR_DIV_8, /**< Divide by 8 */ - IWDG_PRE_16 = IWDG_PR_DIV_16, /**< Divide by 16 */ - IWDG_PRE_32 = IWDG_PR_DIV_32, /**< Divide by 32 */ - IWDG_PRE_64 = IWDG_PR_DIV_64, /**< Divide by 64 */ - IWDG_PRE_128 = IWDG_PR_DIV_128, /**< Divide by 128 */ - IWDG_PRE_256 = IWDG_PR_DIV_256 /**< Divide by 256 */ -} iwdg_prescaler; - -void iwdg_init(iwdg_prescaler prescaler, uint16 reload); -void iwdg_feed(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/libmaple.h b/STM32F3/cores/maple/libmaple/include/libmaple/libmaple.h deleted file mode 100644 index c9034d7..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/libmaple.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/libmaple.h - * @brief General include file for libmaple - */ - -#ifndef _LIBMAPLE_LIBMAPLE_H_ -#define _LIBMAPLE_LIBMAPLE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/libmaple_types.h b/STM32F3/cores/maple/libmaple/include/libmaple/libmaple_types.h deleted file mode 100644 index 60dd2ff..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/libmaple_types.h +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/libmaple_types.h - * - * @brief libmaple's types, and operations on types. - */ - -#ifndef _LIBMAPLE_LIBMAPLE_TYPES_H_ -#define _LIBMAPLE_LIBMAPLE_TYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef unsigned long long uint64; - -typedef signed char int8; -typedef short int16; -typedef int int32; -typedef long long int64; - -typedef void (*voidFuncPtr)(void); -typedef void (*voidArgumentFuncPtr)(void *); - -#define __io volatile -#define __attr_flash __attribute__((section (".USER_FLASH"))) -#define __packed __attribute__((__packed__)) -#define __deprecated __attribute__((__deprecated__)) -#define __weak __attribute__((weak)) -#define __always_inline inline __attribute__((always_inline)) -#define __unused __attribute__((unused)) - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef offsetof -#define offsetof(type, member) __builtin_offsetof(type, member) -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/nvic.h b/STM32F3/cores/maple/libmaple/include/libmaple/nvic.h deleted file mode 100644 index ffe385d..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/nvic.h +++ /dev/null @@ -1,155 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/nvic.h - * @brief Nested vectored interrupt controller support. - * - * Basic usage: - * - * @code - * // Initialise the interrupt controller and point to the vector - * // table at the start of flash. - * nvic_init(0x08000000, 0); - * // Bind in a timer interrupt handler - * timer_attach_interrupt(TIMER_CC1_INTERRUPT, handler); - * // Optionally set the priority - * nvic_irq_set_priority(NVIC_TIMER1_CC, 5); - * // All done, enable all interrupts - * nvic_globalirq_enable(); - * @endcode - */ - -#ifndef _LIBMAPLE_NVIC_H_ -#define _LIBMAPLE_NVIC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -/** NVIC register map type. */ -typedef struct nvic_reg_map { - __io uint32 ISER[8]; /**< Interrupt Set Enable Registers */ - /** Reserved */ - uint32 RESERVED0[24]; - - __io uint32 ICER[8]; /**< Interrupt Clear Enable Registers */ - /** Reserved */ - uint32 RESERVED1[24]; - - __io uint32 ISPR[8]; /**< Interrupt Set Pending Registers */ - /** Reserved */ - uint32 RESERVED2[24]; - - __io uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */ - /** Reserved */ - uint32 RESERVED3[24]; - - __io uint32 IABR[8]; /**< Interrupt Active bit Registers */ - /** Reserved */ - uint32 RESERVED4[56]; - - __io uint8 IP[240]; /**< Interrupt Priority Registers */ - /** Reserved */ - uint32 RESERVED5[644]; - - __io uint32 STIR; /**< Software Trigger Interrupt Registers */ -} nvic_reg_map; - -/** NVIC register map base pointer. */ -#define NVIC_BASE ((struct nvic_reg_map*)0xE000E100) - -/* - * Note: The series header must define enum nvic_irq_num, which gives - * descriptive names to the interrupts and exceptions from NMI (-14) - * to the largest interrupt available in the series, where the value - * for nonnegative enumerators corresponds to its position in the - * vector table. - * - * It also must define a static inline nvic_irq_disable_all(), which - * writes 0xFFFFFFFF to all ICE registers available in the series. (We - * place the include here to give the series header access to - * NVIC_BASE, in order to let it do so). - */ -#include - -void nvic_init(uint32 address, uint32 offset); -void nvic_set_vector_table(uint32 address, uint32 offset); -void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority); -void nvic_sys_reset(); - -/** - * Enables interrupts and configurable fault handlers (clear PRIMASK). - */ -static __always_inline void nvic_globalirq_enable() { - asm volatile("cpsie i"); -} - -/** - * Disable interrupts and configurable fault handlers (set PRIMASK). - */ -static __always_inline void nvic_globalirq_disable() { - asm volatile("cpsid i"); -} - -/** - * @brief Enable interrupt irq_num - * @param irq_num Interrupt to enable - */ -static inline void nvic_irq_enable(nvic_irq_num irq_num) { - if (irq_num < 0) { - return; - } - NVIC_BASE->ISER[irq_num / 32] = BIT(irq_num % 32); -} - -/** - * @brief Disable interrupt irq_num - * @param irq_num Interrupt to disable - */ -static inline void nvic_irq_disable(nvic_irq_num irq_num) { - if (irq_num < 0) { - return; - } - NVIC_BASE->ICER[irq_num / 32] = BIT(irq_num % 32); -} - -/** - * @brief Quickly disable all interrupts. - * - * Calling this function is significantly faster than calling - * nvic_irq_disable() in a loop. - */ -static inline void nvic_irq_disable_all(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/opamp.h b/STM32F3/cores/maple/libmaple/include/libmaple/opamp.h deleted file mode 100644 index 2a0be62..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/opamp.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/include/libmaple/fpu.h - * @author F3-port by Hanspeter Portner - * @brief Floating Point Unit (OPAMP) interace. - */ - -#ifndef _LIBMAPLE_OPAMP_H_ -#define _LIBMAPLE_OPAMP_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/pwr.h b/STM32F3/cores/maple/libmaple/include/libmaple/pwr.h deleted file mode 100644 index e4b5b0d..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/pwr.h +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/pwr.h - * @brief Power control (PWR). - */ - -#ifndef _LIBMAPLE_PWR_H_ -#define _LIBMAPLE_PWR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** Power interface register map. */ -typedef struct pwr_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 CSR; /**< Control and status register */ -} pwr_reg_map; - -/** Power peripheral register map base pointer. */ -#define PWR_BASE ((struct pwr_reg_map*)0x40007000) - -/* - * Register bit definitions - */ - -/* Control register */ - -/** Disable backup domain write protection bit */ -#define PWR_CR_DBP_BIT 8 -/** Power voltage detector enable bit */ -#define PWR_CR_PVDE_BIT 4 -/** Clear standby flag bit */ -#define PWR_CR_CSBF_BIT 3 -/** Clear wakeup flag bit */ -#define PWR_CR_CWUF_BIT 2 -/** Power down deepsleep bit */ -#define PWR_CR_PDDS_BIT 1 -/** Low-power deepsleep bit */ -#define PWR_CR_LPDS_BIT 0 - -/** Disable backup domain write protection */ -#define PWR_CR_DBP (1U << PWR_CR_DBP_BIT) -/** Power voltage detector (PVD) level selection */ -#define PWR_CR_PLS (0x7 << 5) -/** Power voltage detector enable */ -#define PWR_CR_PVDE (1U << PWR_CR_PVDE_BIT) -/** Clear standby flag */ -#define PWR_CR_CSBF (1U << PWR_CR_CSBF_BIT) -/** Clear wakeup flag */ -#define PWR_CR_CWUF (1U << PWR_CR_CWUF_BIT) -/** Power down deepsleep */ -#define PWR_CR_PDDS (1U << PWR_CR_PDDS_BIT) -/** Low-power deepsleep */ -#define PWR_CR_LPDS (1U << PWR_CR_LPDS_BIT) - -/* Control and status register */ - -/** Enable wakeup pin bit */ -#define PWR_CSR_EWUP_BIT 8 -/** PVD output bit */ -#define PWR_CSR_PVDO_BIT 2 -/** Standby flag bit */ -#define PWR_CSR_SBF_BIT 1 -/** Wakeup flag bit */ -#define PWR_CSR_WUF_BIT 0 - -/** Enable wakeup pin */ -#define PWR_CSR_EWUP (1U << PWR_CSR_EWUP_BIT) -/** PVD output */ -#define PWR_CSR_PVDO (1U << PWR_CSR_PVDO_BIT) -/** Standby flag */ -#define PWR_CSR_SBF (1U << PWR_CSR_SBF_BIT) -/** Wakeup flag */ -#define PWR_CSR_WUF (1U << PWR_CSR_WUF_BIT) - -/* - * Convenience functions - */ - -void pwr_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/rcc.h b/STM32F3/cores/maple/libmaple/include/libmaple/rcc.h deleted file mode 100644 index ea16803..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/rcc.h +++ /dev/null @@ -1,175 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/rcc.h - * @brief Reset and Clock Control (RCC) interface. - */ - -#ifndef _LIBMAPLE_RCC_H_ -#define _LIBMAPLE_RCC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* Put the SYSCLK sources before the series header is included, as it - * might need them. */ -/** - * @brief SYSCLK sources - * @see rcc_switch_sysclk() - */ -typedef enum rcc_sysclk_src { - RCC_CLKSRC_HSI = 0x0, - RCC_CLKSRC_HSE = 0x1, - RCC_CLKSRC_PLL = 0x2, -} rcc_sysclk_src; - -#include - -/* Note: Beyond the usual (registers, etc.), it's up to the series - * header to define the following types: - * - * - enum rcc_clk: Available system and secondary clock sources, - * e.g. RCC_CLK_HSE, RCC_CLK_PLL, RCC_CLK_LSE. - * - * Note that the inclusion of secondary clock sources (like LSI and - * LSE) makes enum rcc_clk different from the SYSCLK sources, which - * are defined in this header as enum rcc_sysclk_src. - * - * IMPORTANT NOTE TO IMPLEMENTORS: If you are adding support for a - * new STM32 series, see the comment near rcc_clk_reg() in - * libmaple/rcc.c for information on how to choose these values so - * that rcc_turn_on_clk() etc. will work on your series. - * - * - enum rcc_clk_id: For each available peripheral. These are widely used - * as unique IDs (TODO extricate from RCC?). Peripherals which are - * common across STM32 series should use the same token for their - * rcc_clk_id in each series header. - * - * - enum rcc_clk_domain: For each clock domain. This is returned by - * rcc_dev_clk(). For instance, each AHB and APB is a clock domain. - * - * - enum rcc_prescaler: And a suitable set of dividers for - * rcc_set_prescaler(). - * - * - enum rcc_pllsrc: For each PLL source. Same source, same token. - * - * - A target-dependent type to be pointed to by the data field in a - * struct rcc_pll_cfg. - */ - -#ifdef __DOXYGEN__ -/** RCC register map base pointer */ -#define RCC_BASE -#endif - -/* Clock prescaler management. */ - -/** - * @brief Set the divider on a peripheral prescaler - * @param prescaler prescaler to set - * @param divider prescaler divider - */ -extern void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider); - -/* SYSCLK. */ - -void rcc_switch_sysclk(rcc_sysclk_src sysclk_src); - -/* PLL configuration */ - -/** - * @brief Specifies a configuration for the main PLL. - */ -typedef struct rcc_pll_cfg { - rcc_pllsrc pllsrc; /**< PLL source */ - - /** Series-specific configuration data. */ - void *data; -} rcc_pll_cfg; - -/** - * @brief Configure the main PLL. - * - * You may only call this function while the PLL is disabled. - * - * @param pll_cfg Desired PLL configuration. The contents of this - * struct depend entirely on the target. - */ -extern void rcc_configure_pll(rcc_pll_cfg *pll_cfg); - -/* System and secondary clock sources. */ - -void rcc_turn_on_clk(rcc_clk clock); -void rcc_turn_off_clk(rcc_clk clock); -int rcc_is_clk_on(rcc_clk clock); -int rcc_is_clk_ready(rcc_clk clock); - -/* Peripheral clock lines and clock domains. */ - -/** - * @brief Turn on the clock line on a peripheral - * @param id Clock ID of the peripheral to turn on. - */ -extern void rcc_clk_enable(rcc_clk_id id); - -/** - * @brief Reset a peripheral. - * - * Caution: not all rcc_clk_id values refer to a peripheral which can - * be reset. (Only rcc_clk_ids for peripherals with bits in an RCC - * reset register can be used here.) - * - * @param id Clock ID of the peripheral to reset. - */ -extern void rcc_reset_dev(rcc_clk_id id); - -rcc_clk_domain rcc_dev_clk(rcc_clk_id id); - -/* Clock security system */ - -/** - * @brief Enable the clock security system (CSS). - */ -static inline void rcc_enable_css() { - RCC_BASE->CR |= RCC_CR_CSSON; -} - -/** - * @brief Disable the clock security system (CSS). - */ -static inline void rcc_disable_css() { - RCC_BASE->CR &= ~RCC_CR_CSSON; -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/ring_buffer.h b/STM32F3/cores/maple/libmaple/include/libmaple/ring_buffer.h deleted file mode 100644 index e02e6e7..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/ring_buffer.h +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/ring_buffer.h - * @brief Simple circular buffer - * - * This implementation is not thread-safe. In particular, none of - * these functions is guaranteed re-entrant. - */ - -#ifndef _LIBMAPLE_RING_BUFFER_H_ -#define _LIBMAPLE_RING_BUFFER_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/** - * Ring buffer type. - * - * The buffer is empty when head == tail. - * - * The buffer is full when the head is one byte in front of the tail, - * modulo buffer length. - * - * One byte is left free to distinguish empty from full. */ -typedef struct ring_buffer { - volatile uint8 *buf; /**< Buffer items are stored into */ - uint16 head; /**< Index of the next item to remove */ - uint16 tail; /**< Index where the next item will get inserted */ - uint16 size; /**< Buffer capacity minus one */ -} ring_buffer; - -/** - * Initialise a ring buffer. - * - * @param rb Instance to initialise - * - * @param size Number of items in buf. The ring buffer will always - * leave one element unoccupied, so the maximum number of - * elements it can store will be size - 1. Thus, size - * must be at least 2. - * - * @param buf Buffer to store items into - */ -static inline void rb_init(ring_buffer *rb, uint16 size, uint8 *buf) { - rb->head = 0; - rb->tail = 0; - rb->size = size - 1; - rb->buf = buf; -} - -/** - * @brief Return the number of elements stored in the ring buffer. - * @param rb Buffer whose elements to count. - */ -static inline uint16 rb_full_count(ring_buffer *rb) { - __io ring_buffer *arb = rb; - int32 size = arb->tail - arb->head; - if (arb->tail < arb->head) { - size += arb->size + 1; - } - return (uint16)size; -} - -/** - * @brief Returns true if and only if the ring buffer is full. - * @param rb Buffer to test. - */ -static inline int rb_is_full(ring_buffer *rb) { - return (rb->tail + 1 == rb->head) || - (rb->tail == rb->size && rb->head == 0); -} - -/** - * @brief Returns true if and only if the ring buffer is empty. - * @param rb Buffer to test. - */ -static inline int rb_is_empty(ring_buffer *rb) { - return rb->head == rb->tail; -} - -/** - * Append element onto the end of a ring buffer. - * @param rb Buffer to append onto. - * @param element Value to append. - */ -static inline void rb_insert(ring_buffer *rb, uint8 element) { - rb->buf[rb->tail] = element; - rb->tail = (rb->tail == rb->size) ? 0 : rb->tail + 1; -} - -/** - * @brief Remove and return the first item from a ring buffer. - * @param rb Buffer to remove from, must contain at least one element. - */ -static inline uint8 rb_remove(ring_buffer *rb) { - uint8 ch = rb->buf[rb->head]; - rb->head = (rb->head == rb->size) ? 0 : rb->head + 1; - return ch; -} - -/** - * @brief Attempt to remove the first item from a ring buffer. - * - * If the ring buffer is nonempty, removes and returns its first item. - * If it is empty, does nothing and returns a negative value. - * - * @param rb Buffer to attempt to remove from. - */ -static inline int16 rb_safe_remove(ring_buffer *rb) { - return rb_is_empty(rb) ? -1 : rb_remove(rb); -} - -/** - * @brief Attempt to insert an element into a ring buffer. - * - * @param rb Buffer to insert into. - * @param element Value to insert into rb. - * @sideeffect If rb is not full, appends element onto buffer. - * @return If element was appended, then true; otherwise, false. */ -static inline int rb_safe_insert(ring_buffer *rb, uint8 element) { - if (rb_is_full(rb)) { - return 0; - } - rb_insert(rb, element); - return 1; -} - -/** - * @brief Append an item onto the end of a non-full ring buffer. - * - * If the buffer is full, removes its first item, then inserts the new - * element at the end. - * - * @param rb Ring buffer to insert into. - * @param element Value to insert into ring buffer. - * @return On success, returns -1. If an element was popped, returns - * the popped value. - */ -static inline int rb_push_insert(ring_buffer *rb, uint8 element) { - int ret = -1; - if (rb_is_full(rb)) { - ret = rb_remove(rb); - } - rb_insert(rb, element); - return ret; -} - -/** - * @brief Discard all items from a ring buffer. - * @param rb Ring buffer to discard all items from. - */ -static inline void rb_reset(ring_buffer *rb) { - rb->tail = rb->head; -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/scb.h b/STM32F3/cores/maple/libmaple/include/libmaple/scb.h deleted file mode 100644 index c42a0f2..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/scb.h +++ /dev/null @@ -1,214 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011-2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/scb.h - * @brief System control block header - */ - -/* - * FIXME: STM32F2? - */ - -#ifndef _LIBMAPLE_SCB_H_ -#define _LIBMAPLE_SCB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * Register map and base pointer - */ - -/** System control block register map type */ -typedef struct scb_reg_map { - __io uint32 CPUID; /**< CPU ID Base Register */ - __io uint32 ICSR; /**< Interrupt Control State Register */ - __io uint32 VTOR; /**< Vector Table Offset Register */ - __io uint32 AIRCR; /**< Application Interrupt / Reset Control Register */ - __io uint32 SCR; /**< System Control Register */ - __io uint32 CCR; /**< Configuration and Control Register */ - __io uint8 SHP[12]; /**< System Handler Priority Registers - (4-7, 8-11, 12-15) */ - __io uint32 SHCSR; /**< System Handler Control and State Register */ - __io uint32 CFSR; /**< Configurable Fault Status Register */ - __io uint32 HFSR; /**< Hard Fault Status Register */ - /* DFSR is not documented by ST in PM0056 (as of Revision 4), but - * there's a 4 byte hole in the SCB register map docs right where - * it belongs. Since it's specified as "always implemented" in - * the ARM v7-M ARM, I'm assuming its absence is a bug in the ST - * doc, but I haven't proven it. [mbolivar] */ - __io uint32 DFSR; /**< Debug Fault Status Register */ - __io uint32 MMFAR; /**< Mem Manage Address Register */ - __io uint32 BFAR; /**< Bus Fault Address Register */ -#if 0 - /* The following registers are implementation-defined according to - * ARM v7-M, and I can't find evidence of their existence in ST's - * docs. I'm removing them. Feel free to yell at me if they do - * exist. [mbolivar] - */ - __io uint32 AFSR; /**< Auxiliary Fault Status Register */ - __io uint32 PFR[2]; /**< Processor Feature Register */ - __io uint32 DFR; /**< Debug Feature Register */ - __io uint32 AFR; /**< Auxiliary Feature Register */ - __io uint32 MMFR[4]; /**< Memory Model Feature Register */ - __io uint32 ISAR[5]; /**< ISA Feature Register */ -#endif -} scb_reg_map; - -/** System control block register map base pointer */ -#define SCB_BASE ((struct scb_reg_map*)0xE000ED00) - -/* - * Register bit definitions - */ - -/* No SCB_REG_FIELD_BIT macros as the relevant addresses are not in a - * bit-band region. */ - -/* CPUID base register (SCB_CPUID) */ - -#define SCB_CPUID_IMPLEMENTER (0xFF << 24) -#define SCB_CPUID_VARIANT (0xF << 20) -#define SCB_CPUID_CONSTANT (0xF << 16) -#define SCB_CPUID_PARTNO (0xFFF << 4) -#define SCB_CPUID_REVISION 0xF - -/* Interrupt control state register (SCB_ICSR) */ - -#define SCB_ICSR_NMIPENDSET (1U << 31) -#define SCB_ICSR_PENDSVSET (1U << 28) -#define SCB_ICSR_PENDSVCLR (1U << 27) -#define SCB_ICSR_PENDSTSET (1U << 26) -#define SCB_ICSR_PENDSTCLR (1U << 25) -#define SCB_ICSR_ISRPENDING (1U << 22) -#define SCB_ICSR_VECTPENDING (0x3FF << 12) -#define SCB_ICSR_RETOBASE (1U << 11) -#define SCB_ICSR_VECTACTIVE 0xFF - -/* Vector table offset register (SCB_VTOR) */ - -#define SCB_VTOR_TBLOFF (0x1FFFFF << 9) - -/* Application interrupt and reset control register (SCB_AIRCR) */ - -#define SCB_AIRCR_VECTKEYSTAT (0x5FA << 16) -#define SCB_AIRCR_VECTKEY (0x5FA << 16) -#define SCB_AIRCR_ENDIANNESS (1U << 15) -#define SCB_AIRCR_PRIGROUP (0x3 << 8) -#define SCB_AIRCR_SYSRESETREQ (1U << 2) -#define SCB_AIRCR_VECTCLRACTIVE (1U << 1) -#define SCB_AIRCR_VECTRESET (1U << 0) - -/* System control register (SCB_SCR) */ - -#define SCB_SCR_SEVONPEND (1U << 4) -#define SCB_SCR_SLEEPDEEP (1U << 2) -#define SCB_SCR_SLEEPONEXIT (1U << 1) - -/* Configuration and Control Register (SCB_CCR) */ - -#define SCB_CCR_STKALIGN (1U << 9) -#define SCB_CCR_BFHFNMIGN (1U << 8) -#define SCB_CCR_DIV_0_TRP (1U << 4) -#define SCB_CCR_UNALIGN_TRP (1U << 3) -#define SCB_CCR_USERSETMPEND (1U << 1) -#define SCB_CCR_NONBASETHRDENA (1U << 0) - -/* System handler priority registers (SCB_SHPRx) */ - -#define SCB_SHPR1_PRI6 (0xFF << 16) -#define SCB_SHPR1_PRI5 (0xFF << 8) -#define SCB_SHPR1_PRI4 0xFF - -#define SCB_SHPR2_PRI11 (0xFF << 24) - -#define SCB_SHPR3_PRI15 (0xFF << 24) -#define SCB_SHPR3_PRI14 (0xFF << 16) - -/* System Handler Control and state register (SCB_SHCSR) */ - -#define SCB_SHCSR_USGFAULTENA (1U << 18) -#define SCB_SHCSR_BUSFAULTENA (1U << 17) -#define SCB_SHCSR_MEMFAULTENA (1U << 16) -#define SCB_SHCSR_SVCALLPENDED (1U << 15) -#define SCB_SHCSR_BUSFAULTPENDED (1U << 14) -#define SCB_SHCSR_MEMFAULTPENDED (1U << 13) -#define SCB_SHCSR_USGFAULTPENDED (1U << 12) -#define SCB_SHCSR_SYSTICKACT (1U << 11) -#define SCB_SHCSR_PENDSVACT (1U << 10) -#define SCB_SHCSR_MONITORACT (1U << 8) -#define SCB_SHCSR_SVCALLACT (1U << 7) -#define SCB_SHCSR_USGFAULTACT (1U << 3) -#define SCB_SHCSR_BUSFAULTACT (1U << 1) -#define SCB_SHCSR_MEMFAULTACT (1U << 0) - -/* Configurable fault status register (SCB_CFSR) */ - -#define SCB_CFSR_DIVBYZERO (1U << 25) -#define SCB_CFSR_UNALIGNED (1U << 24) -#define SCB_CFSR_NOCP (1U << 19) -#define SCB_CFSR_INVPC (1U << 18) -#define SCB_CFSR_INVSTATE (1U << 17) -#define SCB_CFSR_UNDEFINSTR (1U << 16) -#define SCB_CFSR_BFARVALID (1U << 15) -#define SCB_CFSR_STKERR (1U << 12) -#define SCB_CFSR_UNSTKERR (1U << 11) -#define SCB_CFSR_IMPRECISERR (1U << 10) -#define SCB_CFSR_PRECISERR (1U << 9) -#define SCB_CFSR_IBUSERR (1U << 8) -#define SCB_CFSR_MMARVALID (1U << 7) -#define SCB_CFSR_MSTKERR (1U << 4) -#define SCB_CFSR_MUNSTKERR (1U << 3) -#define SCB_CFSR_DACCVIOL (1U << 1) -#define SCB_CFSR_IACCVIOL (1U << 0) - -/* Hard Fault Status Register (SCB_HFSR) */ - -#define SCB_HFSR_DEBUG_VT (1U << 31) -#define SCB_CFSR_FORCED (1U << 30) -#define SCB_CFSR_VECTTBL (1U << 1) - -/* Debug Fault Status Register */ - -/* Not specified by PM0056, but required by ARM. The bit definitions - * here are based on the names given in the ARM v7-M ARM. */ - -#define SCB_DFSR_EXTERNAL (1U << 4) -#define SCB_DFSR_VCATCH (1U << 3) -#define SCB_DFSR_DWTTRAP (1U << 2) -#define SCB_DFSR_BKPT (1U << 1) -#define SCB_DFSR_HALTED (1U << 0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/spi.h b/STM32F3/cores/maple/libmaple/include/libmaple/spi.h deleted file mode 100644 index e688e4f..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/spi.h +++ /dev/null @@ -1,487 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/spi.h - * @author Marti Bolivar , - * F3-port by Hanspeter Portner - * @brief Serial Peripheral Interface (SPI) and Integrated - * Interchip Sound (I2S) peripheral support. - * - * I2S support is currently limited to register maps and bit definitions. - */ - -#ifndef _LIBMAPLE_SPI_H_ -#define _LIBMAPLE_SPI_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -/* - * Register maps - */ - -/** SPI register map type. */ -typedef struct spi_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SR; /**< Status register */ - __io uint32 DR; /**< Data register */ - __io uint32 CRCPR; /**< CRC polynomial register */ - __io uint32 RXCRCR; /**< RX CRC register */ - __io uint32 TXCRCR; /**< TX CRC register */ - __io uint32 I2SCFGR; /**< I2S configuration register */ - __io uint32 I2SPR; /**< I2S prescaler register */ -} spi_reg_map; - -/* - * Register bit definitions - */ - -/* Control register 1 */ - -#define SPI_CR1_BIDIMODE_BIT 15 -#define SPI_CR1_BIDIOE_BIT 14 -#define SPI_CR1_CRCEN_BIT 13 -#define SPI_CR1_CRCNEXT_BIT 12 -#define SPI_CR1_DFF_BIT 11 /* FIXME F3 incompatibility */ -#define SPI_CR1_RXONLY_BIT 10 -#define SPI_CR1_SSM_BIT 9 -#define SPI_CR1_SSI_BIT 8 -#define SPI_CR1_LSBFIRST_BIT 7 -#define SPI_CR1_SPE_BIT 6 -#define SPI_CR1_MSTR_BIT 2 -#define SPI_CR1_CPOL_BIT 1 -#define SPI_CR1_CPHA_BIT 0 - -#define SPI_CR1_BIDIMODE (1U << SPI_CR1_BIDIMODE_BIT) -#define SPI_CR1_BIDIMODE_2_LINE (0x0 << SPI_CR1_BIDIMODE_BIT) -#define SPI_CR1_BIDIMODE_1_LINE (0x1 << SPI_CR1_BIDIMODE_BIT) -#define SPI_CR1_BIDIOE (1U << SPI_CR1_BIDIOE_BIT) -#define SPI_CR1_CRCEN (1U << SPI_CR1_CRCEN_BIT) -#define SPI_CR1_CRCNEXT (1U << SPI_CR1_CRCNEXT_BIT) -#define SPI_CR1_DFF (1U << SPI_CR1_DFF_BIT) -#define SPI_CR1_DFF_8_BIT (0x0 << SPI_CR1_DFF_BIT) -#define SPI_CR1_DFF_16_BIT (0x1 << SPI_CR1_DFF_BIT) -#define SPI_CR1_RXONLY (1U << SPI_CR1_RXONLY_BIT) -#define SPI_CR1_SSM (1U << SPI_CR1_SSM_BIT) -#define SPI_CR1_SSI (1U << SPI_CR1_SSI_BIT) -#define SPI_CR1_LSBFIRST (1U << SPI_CR1_LSBFIRST_BIT) -#define SPI_CR1_SPE (1U << SPI_CR1_SPE_BIT) -#define SPI_CR1_BR (0x7 << 3) -#define SPI_CR1_BR_PCLK_DIV_2 (0x0 << 3) -#define SPI_CR1_BR_PCLK_DIV_4 (0x1 << 3) -#define SPI_CR1_BR_PCLK_DIV_8 (0x2 << 3) -#define SPI_CR1_BR_PCLK_DIV_16 (0x3 << 3) -#define SPI_CR1_BR_PCLK_DIV_32 (0x4 << 3) -#define SPI_CR1_BR_PCLK_DIV_64 (0x5 << 3) -#define SPI_CR1_BR_PCLK_DIV_128 (0x6 << 3) -#define SPI_CR1_BR_PCLK_DIV_256 (0x7 << 3) -#define SPI_CR1_MSTR (1U << SPI_CR1_MSTR_BIT) -#define SPI_CR1_CPOL (1U << SPI_CR1_CPOL_BIT) -#define SPI_CR1_CPOL_LOW (0x0 << SPI_CR1_CPOL_BIT) -#define SPI_CR1_CPOL_HIGH (0x1 << SPI_CR1_CPOL_BIT) -#define SPI_CR1_CPHA (1U << SPI_CR1_CPHA_BIT) - -/* Control register 2 */ - -#define SPI_CR2_TXEIE_BIT 7 -#define SPI_CR2_RXNEIE_BIT 6 -#define SPI_CR2_ERRIE_BIT 5 -#define SPI_CR2_SSOE_BIT 2 -#define SPI_CR2_TXDMAEN_BIT 1 -#define SPI_CR2_RXDMAEN_BIT 0 - -#define SPI_CR2_TXEIE (1U << SPI_CR2_TXEIE_BIT) -#define SPI_CR2_RXNEIE (1U << SPI_CR2_RXNEIE_BIT) -#define SPI_CR2_ERRIE (1U << SPI_CR2_ERRIE_BIT) -#define SPI_CR2_SSOE (1U << SPI_CR2_SSOE_BIT) -#define SPI_CR2_TXDMAEN (1U << SPI_CR2_TXDMAEN_BIT) -#define SPI_CR2_RXDMAEN (1U << SPI_CR2_RXDMAEN_BIT) - -/* Status register */ - -#define SPI_SR_BSY_BIT 7 -#define SPI_SR_OVR_BIT 6 -#define SPI_SR_MODF_BIT 5 -#define SPI_SR_CRCERR_BIT 4 -#define SPI_SR_UDR_BIT 3 -#define SPI_SR_CHSIDE_BIT 2 -#define SPI_SR_TXE_BIT 1 -#define SPI_SR_RXNE_BIT 0 - -#define SPI_SR_BSY (1U << SPI_SR_BSY_BIT) -#define SPI_SR_OVR (1U << SPI_SR_OVR_BIT) -#define SPI_SR_MODF (1U << SPI_SR_MODF_BIT) -#define SPI_SR_CRCERR (1U << SPI_SR_CRCERR_BIT) -#define SPI_SR_UDR (1U << SPI_SR_UDR_BIT) -#define SPI_SR_CHSIDE (1U << SPI_SR_CHSIDE_BIT) -#define SPI_SR_CHSIDE_LEFT (0x0 << SPI_SR_CHSIDE_BIT) -#define SPI_SR_CHSIDE_RIGHT (0x1 << SPI_SR_CHSIDE_BIT) -#define SPI_SR_TXE (1U << SPI_SR_TXE_BIT) -#define SPI_SR_RXNE (1U << SPI_SR_RXNE_BIT) - -/* I2S configuration register */ - -#define SPI_I2SCFGR_I2SMOD_BIT 11 -#define SPI_I2SCFGR_I2SE_BIT 10 -#define SPI_I2SCFGR_PCMSYNC_BIT 7 -#define SPI_I2SCFGR_CKPOL_BIT 3 -#define SPI_I2SCFGR_CHLEN_BIT 0 - -#define SPI_I2SCFGR_I2SMOD (1U << SPI_I2SCFGR_I2SMOD_BIT) -#define SPI_I2SCFGR_I2SMOD_SPI (0x0 << SPI_I2SCFGR_I2SMOD_BIT) -#define SPI_I2SCFGR_I2SMOD_I2S (0x1 << SPI_I2SCFGR_I2SMOD_BIT) -#define SPI_I2SCFGR_I2SE (1U << SPI_I2SCFGR_I2SE_BIT) -#define SPI_I2SCFGR_I2SCFG (0x3 << 8) -#define SPI_I2SCFGR_I2SCFG_SLAVE_TX (0x0 << 8) -#define SPI_I2SCFGR_I2SCFG_SLAVE_RX (0x1 << 8) -#define SPI_I2SCFGR_I2SCFG_MASTER_TX (0x2 << 8) -#define SPI_I2SCFGR_I2SCFG_MASTER_RX (0x3 << 8) -#define SPI_I2SCFGR_PCMSYNC (1U << SPI_I2SCFGR_PCMSYNC_BIT) -#define SPI_I2SCFGR_PCMSYNC_SHORT (0x0 << SPI_I2SCFGR_PCMSYNC_BIT) -#define SPI_I2SCFGR_PCMSYNC_LONG (0x1 << SPI_I2SCFGR_PCMSYNC_BIT) -#define SPI_I2SCFGR_I2SSTD (0x3 << 4) -#define SPI_I2SCFGR_I2SSTD_PHILLIPS (0x0 << 4) -#define SPI_I2SCFGR_I2SSTD_MSB (0x1 << 4) -#define SPI_I2SCFGR_I2SSTD_LSB (0x2 << 4) -#define SPI_I2SCFGR_I2SSTD_PCM (0x3 << 4) -#define SPI_I2SCFGR_CKPOL (1U << SPI_I2SCFGR_CKPOL_BIT) -#define SPI_I2SCFGR_CKPOL_LOW (0x0 << SPI_I2SCFGR_CKPOL_BIT) -#define SPI_I2SCFGR_CKPOL_HIGH (0x1 << SPI_I2SCFGR_CKPOL_BIT) -#define SPI_I2SCFGR_DATLEN (0x3 << 1) -#define SPI_I2SCFGR_DATLEN_16_BIT (0x0 << 1) -#define SPI_I2SCFGR_DATLEN_24_BIT (0x1 << 1) -#define SPI_I2SCFGR_DATLEN_32_BIT (0x2 << 1) -#define SPI_I2SCFGR_CHLEN (1U << SPI_I2SCFGR_CHLEN_BIT) -#define SPI_I2SCFGR_CHLEN_16_BIT (0x0 << SPI_I2SCFGR_CHLEN_BIT) -#define SPI_I2SCFGR_CHLEN_32_BIT (0x1 << SPI_I2SCFGR_CHLEN_BIT) - -/* I2S prescaler register */ - -#define SPI_I2SPR_MCKOE_BIT 9 -#define SPI_I2SPR_ODD_BIT 8 - -#define SPI_I2SPR_MCKOE (1U << SPI_I2SPR_MCKOE_BIT) -#define SPI_I2SPR_ODD (1U << SPI_I2SPR_ODD_BIT) -#define SPI_I2SPR_I2SDIV 0xFF - -/* - * Devices - */ - -/** SPI device type */ -typedef struct spi_dev { - spi_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - nvic_irq_num irq_num; /**< NVIC interrupt number */ -} spi_dev; - -/* - * SPI Convenience functions - */ - -void spi_init(spi_dev *dev); - -struct gpio_dev; -/** - * @brief Configure GPIO bit modes for use as a SPI port's pins. - * - * @param dev SPI device - * @param as_master If true, configure as bus master; otherwise, as slave. - * @param nss_dev NSS pin's GPIO device - * @param nss_bit NSS pin's GPIO bit on nss_dev - * @param comm_dev SCK, MISO, MOSI pins' GPIO device - * @param sck_bit SCK pin's GPIO bit on comm_dev - * @param miso_bit MISO pin's GPIO bit on comm_dev - * @param mosi_bit MOSI pin's GPIO bit on comm_dev - */ -extern void spi_config_gpios(spi_dev *dev, - uint8 as_master, - struct gpio_dev *nss_dev, - uint8 nss_bit, - struct gpio_dev *comm_dev, - uint8 sck_bit, - uint8 miso_bit, - uint8 mosi_bit); - -/** - * @brief SPI mode configuration. - * - * A SPI mode determines a combination of the idle state of the clock - * line (the clock polarity, or "CPOL"), and which clock edge triggers - * data capture (the clock phase, or "CPHA"). - */ -typedef enum spi_mode { - /** Clock idles low, data captured on rising edge (first transition) */ - SPI_MODE_LOW_RISING = 0, - /** Clock idles low, data captured on falling edge (second transition) */ - SPI_MODE_LOW_FALLING = 1, - /** Clock idles high, data captured on falling edge (first transition) */ - SPI_MODE_HIGH_FALLING = 2, - /** Clock idles high, data captured on rising edge (second transition) */ - SPI_MODE_HIGH_RISING = 3, - - SPI_MODE_0 = SPI_MODE_LOW_RISING, /**< Same as SPI_MODE_LOW_RISING */ - SPI_MODE_1 = SPI_MODE_LOW_FALLING, /**< Same as SPI_MODE_LOW_FALLING */ - SPI_MODE_2 = SPI_MODE_HIGH_FALLING, /**< Same as SPI_MODE_HIGH_FALLING */ - SPI_MODE_3 = SPI_MODE_HIGH_RISING, /**< Same as SPI_MODE_HIGH_RISING */ -} spi_mode; - -/** - * @brief SPI baud rate configuration, as a divisor of f_PCLK, the - * PCLK clock frequency. - */ -typedef enum spi_baud_rate { - SPI_BAUD_PCLK_DIV_2 = SPI_CR1_BR_PCLK_DIV_2, /**< f_PCLK/2 */ - SPI_BAUD_PCLK_DIV_4 = SPI_CR1_BR_PCLK_DIV_4, /**< f_PCLK/4 */ - SPI_BAUD_PCLK_DIV_8 = SPI_CR1_BR_PCLK_DIV_8, /**< f_PCLK/8 */ - SPI_BAUD_PCLK_DIV_16 = SPI_CR1_BR_PCLK_DIV_16, /**< f_PCLK/16 */ - SPI_BAUD_PCLK_DIV_32 = SPI_CR1_BR_PCLK_DIV_32, /**< f_PCLK/32 */ - SPI_BAUD_PCLK_DIV_64 = SPI_CR1_BR_PCLK_DIV_64, /**< f_PCLK/64 */ - SPI_BAUD_PCLK_DIV_128 = SPI_CR1_BR_PCLK_DIV_128, /**< f_PCLK/128 */ - SPI_BAUD_PCLK_DIV_256 = SPI_CR1_BR_PCLK_DIV_256, /**< f_PCLK/256 */ -} spi_baud_rate; - -/** - * @brief SPI initialization flags. - * @see spi_master_enable() - * @see spi_slave_enable() - */ -typedef enum spi_cfg_flag { - SPI_BIDIMODE = SPI_CR1_BIDIMODE, /**< Bidirectional mode enable */ - SPI_BIDIOE = SPI_CR1_BIDIOE, /**< Output enable in bidirectional - mode */ - SPI_CRCEN = SPI_CR1_CRCEN, /**< Cyclic redundancy check (CRC) - enable */ - SPI_DFF_8_BIT = SPI_CR1_DFF_8_BIT, /**< 8-bit data frame format (this is - the default) */ - SPI_DFF_16_BIT = SPI_CR1_DFF_16_BIT, /**< 16-bit data frame format */ - SPI_RX_ONLY = SPI_CR1_RXONLY, /**< Receive only */ - SPI_SW_SLAVE = SPI_CR1_SSM, /**< Software slave management */ - SPI_SOFT_SS = SPI_CR1_SSI, /**< Software (internal) slave - select. This flag only has an - effect when used in combination - with SPI_SW_SLAVE. */ - SPI_FRAME_LSB = SPI_CR1_LSBFIRST, /**< LSB-first (little-endian) frame - format */ - SPI_FRAME_MSB = 0, /**< MSB-first (big-endian) frame - format (this is the default) */ -} spi_cfg_flag; - -void spi_master_enable(spi_dev *dev, - spi_baud_rate baud, - spi_mode mode, - uint32 flags); - -void spi_slave_enable(spi_dev *dev, - spi_mode mode, - uint32 flags); - -uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len); - -/** - * @brief Call a function on each SPI port - * @param fn Function to call. - */ -extern void spi_foreach(void (*fn)(spi_dev*)); - -void spi_peripheral_enable(spi_dev *dev); -void spi_peripheral_disable(spi_dev *dev); - -void spi_tx_dma_enable(spi_dev *dev); -void spi_tx_dma_disable(spi_dev *dev); - -void spi_rx_dma_enable(spi_dev *dev); -void spi_rx_dma_disable(spi_dev *dev); - -/** - * @brief Determine if a SPI peripheral is enabled. - * @param dev SPI device - * @return True, if and only if dev's peripheral is enabled. - */ -static inline uint8 spi_is_enabled(spi_dev *dev) { - return dev->regs->CR1 & SPI_CR1_SPE_BIT; -} - -/** - * @brief Disable all SPI peripherals - */ -static inline void spi_peripheral_disable_all(void) { - spi_foreach(spi_peripheral_disable); -} - -/** Available SPI interrupts */ -typedef enum spi_interrupt { - SPI_TXE_INTERRUPT = SPI_CR2_TXEIE, /**< TX buffer empty interrupt */ - SPI_RXNE_INTERRUPT = SPI_CR2_RXNEIE, /**< RX buffer not empty interrupt */ - SPI_ERR_INTERRUPT = SPI_CR2_ERRIE /**< - * Error interrupt (CRC, overrun, - * and mode fault errors for SPI; - * underrun, overrun errors for I2S) - */ -} spi_interrupt; - -/** - * @brief Mask for all spi_interrupt values - * @see spi_interrupt - */ -#define SPI_INTERRUPTS_ALL (SPI_TXE_INTERRUPT | \ - SPI_RXNE_INTERRUPT | \ - SPI_ERR_INTERRUPT) - -/** - * @brief Enable SPI interrupt requests - * @param dev SPI device - * @param interrupt_flags Bitwise OR of spi_interrupt values to enable - * @see spi_interrupt - */ -static inline void spi_irq_enable(spi_dev *dev, uint32 interrupt_flags) { - dev->regs->CR2 |= interrupt_flags; - nvic_irq_enable(dev->irq_num); -} - -/** - * @brief Disable SPI interrupt requests - * @param dev SPI device - * @param interrupt_flags Bitwise OR of spi_interrupt values to disable - * @see spi_interrupt - */ -static inline void spi_irq_disable(spi_dev *dev, uint32 interrupt_flags) { - dev->regs->CR2 &= ~interrupt_flags; -} - -/** - * @brief Get the data frame format flags with which a SPI port is - * configured. - * @param dev SPI device whose data frame format to get. - * @return SPI_DFF_8_BIT, if dev has an 8-bit data frame format. - * Otherwise, SPI_DFF_16_BIT. - */ -static inline spi_cfg_flag spi_dff(spi_dev *dev) { - return ((dev->regs->CR1 & SPI_CR1_DFF) == SPI_CR1_DFF_8_BIT ? - SPI_DFF_8_BIT : - SPI_DFF_16_BIT); -} - -/** - * @brief Determine whether the device's peripheral receive (RX) - * register is empty. - * @param dev SPI device - * @return true, iff dev's RX register is empty. - */ -static inline uint8 spi_is_rx_nonempty(spi_dev *dev) { - return dev->regs->SR & SPI_SR_RXNE; -} - -/** - * @brief Retrieve the contents of the device's peripheral receive - * (RX) register. - * - * You may only call this function when the RX register is nonempty. - * Calling this function clears the contents of the RX register. - * - * @param dev SPI device - * @return Contents of dev's peripheral RX register - * @see spi_is_rx_reg_nonempty() - */ -extern uint16 spi_rx_reg(spi_dev *dev); - -/** - * @brief Determine whether the device's peripheral transmit (TX) - * register is empty. - * @param dev SPI device - * @return true, iff dev's TX register is empty. - */ -static inline uint8 spi_is_tx_empty(spi_dev *dev) { - return dev->regs->SR & SPI_SR_TXE; -} - -/** - * @brief Nonblocking SPI transmit. - * @param dev SPI port to use for transmission - * @param buf Buffer to transmit. The sizeof buf's elements are - * inferred from dev's data frame format (i.e., are - * correctly treated as 8-bit or 16-bit quantities). - * @param len Maximum number of elements to transmit. - * @return Number of elements transmitted. - */ -extern uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len); - -/** - * @brief Load a value into the device's peripheral transmit (TX) register. - * - * You may only call this function when the TX register is empty. - * Calling this function loads val into the peripheral's TX register. - * If the device is properly configured, this will initiate a - * transmission, the completion of which will cause the TX register to - * be empty again. - * - * @param dev SPI device - * @param val Value to load into the TX register. If the SPI data - * frame format is 8 bit, the value must be right-aligned. - * @see spi_is_tx_reg_empty() - * @see spi_init() - * @see spi_master_enable() - * @see spi_slave_enable() - */ -static inline void spi_tx_reg(spi_dev *dev, uint16 val) { - dev->regs->DR = val; /* FIXME F3 incompatibility */ -} - -/** - * @brief Determine whether the device's peripheral busy (SPI_SR_BSY) - * flag is set. - * @param dev SPI device - * @return true, iff dev's BSY flag is set. - */ -static inline uint8 spi_is_busy(spi_dev *dev) { - return dev->regs->SR & SPI_SR_BSY; -} - -/* - * SPI auxiliary routines - */ - -extern void spi_reconfigure(spi_dev *dev, uint32 cr1_config); - -/* - * I2S convenience functions (TODO) - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/stm32.h b/STM32F3/cores/maple/libmaple/include/libmaple/stm32.h deleted file mode 100644 index f7ced23..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/stm32.h +++ /dev/null @@ -1,239 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010, 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/stm32.h - * @brief STM32 chip header - * - * This header supplies various chip-specific values for the current - * build target. It's useful both to abstract away hardware details - * (e.g. through use of STM32_NR_INTERRUPTS) and to decide what to do - * when you want something nonportable (e.g. by checking - * STM32_MCU_SERIES). - */ - -#ifndef _LIBMAPLE_STM32_H_ -#define _LIBMAPLE_STM32_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * STM32 series identifiers. - * - * Don't make these into an enum; the preprocessor needs them. - */ - -/** STM32F1 series. */ -#define STM32_SERIES_F1 0 -/** STM32F2 series. */ -#define STM32_SERIES_F2 1 -/** STM32L1 series. */ -#define STM32_SERIES_L1 2 -/** STM32F3 series. */ -#define STM32_SERIES_F3 3 -/** STM32F4 series. */ -#define STM32_SERIES_F4 4 - -/* The series header is responsible for defining: - * - * - Everything in the following __DOXYGEN__ conditional block. - * - * - STM32_HAVE_FSMC: 1 if the MCU has the FSMC peripheral, and 0 - * otherwise. - * - * - STM32_HAVE_USB: 1 if the MCU has a USB peripheral, and 0 - * otherwise. - */ -#include - -/* Ensure the series header isn't broken. */ -#if (!defined(STM32_PCLK1) || \ - !defined(STM32_PCLK2) || \ - !defined(STM32_MCU_SERIES) || \ - !defined(STM32_NR_INTERRUPTS) || \ - !defined(STM32_NR_GPIO_PORTS) || \ - !defined(STM32_TIMER_MASK) || \ - !defined(STM32_DELAY_US_MULT) || \ - !defined(STM32_SRAM_END) || \ - !defined(STM32_HAVE_DAC) || \ - !defined(STM32_HAVE_FSMC) || \ - !defined(STM32_HAVE_USB)) -#error "Bad STM32F1 configuration. Check header for your MCU." -#endif - -/* - * Derived macros - */ - -/* FIXME [0.0.13] add this to ReST API page */ -/** - * @brief Statically determine whether a timer is present. - * - * Given a constant timer number n (starting from 1), this macro has a - * nonzero value exactly when TIMERn is available. - */ -#define STM32_HAVE_TIMER(n) (STM32_TIMER_MASK & (1 << (n))) - -/* - * Doxygen for functionality provided by series header. - */ - -#ifdef __DOXYGEN__ - -/* - * Clock configuration. - * - * These defines depend upon how the MCU is configured. Because of - * the potential for a mismatch between them and the actual clock - * configuration, keep their number to a minimum. - */ - -/** - * @brief APB1 clock speed, in Hz. - */ -#define STM32_PCLK1 - -/** - * @brief APB2 clock speed, in Hz. - */ -#define STM32_PCLK2 - -/** @brief Deprecated. Use STM32_PCLK1 instead. */ -#define PCLK1 -/** @brief Deprecated. Use STM32_PCLK2 instead. */ -#define PCLK2 - -/* - * Series- and MCU-specific values. - */ - -/** - * @brief STM32 series value for the MCU being targeted. - * - * At time of writing, allowed values are: STM32_SERIES_F1, - * STM32_SERIES_F2. This set of values will expand as libmaple adds - * support for more STM32 series MCUs. - */ -#define STM32_MCU_SERIES - -/** - * @brief Number of interrupts in the vector table. - * - * This does not include Cortex-M interrupts (NMI, HardFault, etc.). - */ -#define STM32_NR_INTERRUPTS - -/** - * Number of GPIO ports. - */ -#define STM32_NR_GPIO_PORTS - -/* FIXME [0.0.13] add this to ReST API page */ -/** - * @brief Bitmask of timers available on the MCU. - * - * That is, if TIMERn is available, then STM32_TIMER_MASK & (1 << n) - * will be nonzero. For example, a nonzero value of "STM32_TIMER_MASK - * & 0x2" means TIMER1 is available. - * - * A bitmask is necessary as some STM32 MCUs have "holes" in the range - * of available timers. - */ -#define STM32_TIMER_MASK - -/** - * @brief Multiplier to convert microseconds into loop iterations - * in delay_us(). - * - * @see delay_us() - */ -#define STM32_DELAY_US_MULT - -/** - * @brief Pointer to end of built-in SRAM. - * - * Points to the address which is 1 byte past the last valid - * SRAM address. - */ -#define STM32_SRAM_END - -/** - * @brief 1 if the target MCU has a DAC, and 0 otherwise. - */ -#define STM32_HAVE_DAC - -/** - * @brief 1 if the target MCU has the FSMC peripheral, and 0 otherwise. - * - * Note that the feature set of the FSMC peripheral is restricted on - * some MCUs. - */ -#define STM32_HAVE_FSMC - -/** - * @brief 1 if the target MCU has a USB peripheral, and 0 otherwise. - * - * Note that a variety of USB peripherals are available across the - * different series, with widely varying feature sets and programming - * interfaces. This macro will be 1 if any such peripheral is present. - */ -#define STM32_HAVE_USB - -#endif /* __DOXYGEN__ */ - -/* - * The following are for backwards compatibility only. - */ - -/* PCLK1 and PCLK2 are for backwards compatibility only; don't use in - * new code. */ -#ifndef PCLK1 -#define PCLK1 STM32_PCLK1 -#endif -#if PCLK1 != STM32_PCLK1 -#error "PCLK1 (which is deprecated) differs from STM32_PCLK1." -#endif -#ifndef PCLK2 -#define PCLK2 STM32_PCLK2 -#endif -#if PCLK2 != STM32_PCLK2 -#error "PCLK2 (which is deprecated) differs from STM32_PCLK2." -#endif - -/** @brief Deprecated. Use STM32_NR_INTERRUPTS instead. */ -#define NR_INTERRUPTS STM32_NR_INTERRUPTS -/** @brief Deprecated. Use STM32_NR_GPIO_PORTS instead. */ -#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS -/** @brief Deprecated. Use STM32_DELAY_US_MULT instead. */ -#define DELAY_US_MULT STM32_DELAY_US_MULT - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/syscfg.h b/STM32F3/cores/maple/libmaple/include/libmaple/syscfg.h deleted file mode 100644 index b8c901f..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/syscfg.h +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/syscfg.h - * @author F3-port by Hanspeter Portner - * @brief System configuration controller (SYSCFG) - * - * Availability: STM32F2, STM32F3, STM32F4. - */ - -#ifndef _LIBMAPLE_SYSCFG_H_ -#define _LIBMAPLE_SYSCFG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/* External interrupt configuration register 1 */ - -#define SYSCFG_EXTICR1_EXTI0 0xF -#define SYSCFG_EXTICR1_EXTI1 0xF0 -#define SYSCFG_EXTICR1_EXTI2 0xF00 -#define SYSCFG_EXTICR1_EXTI3 0xF000 - -/* External interrupt configuration register 2 */ - -#define SYSCFG_EXTICR2_EXTI4 0xF -#define SYSCFG_EXTICR2_EXTI5 0xF0 -#define SYSCFG_EXTICR2_EXTI6 0xF00 -#define SYSCFG_EXTICR2_EXTI7 0xF000 - -/* External interrupt configuration register 3 */ - -#define SYSCFG_EXTICR3_EXTI8 0xF -#define SYSCFG_EXTICR3_EXTI9 0xF0 -#define SYSCFG_EXTICR3_EXTI10 0xF00 -#define SYSCFG_EXTICR3_EXTI11 0xF000 - -/* External interrupt configuration register 4 */ - -#define SYSCFG_EXTICR4_EXTI12 0xF -#define SYSCFG_EXTICR4_EXTI13 0xF0 -#define SYSCFG_EXTICR4_EXTI14 0xF00 -#define SYSCFG_EXTICR4_EXTI15 0xF000 - -/* - * Routines - */ - -/** - * @brief Initialize the SYSCFG peripheral. - */ -void syscfg_init(void); - -/** - * @brief System memory mode - * These values specify what memory to map to address 0x00000000. - * @see syscfg_set_mem_mode - */ -typedef enum syscfg_mem_mode { - /** Main flash memory is mapped at 0x0. */ - SYSCFG_MEM_MODE_FLASH = 0x0, - /** System flash (i.e. ST's baked-in bootloader) is mapped at 0x0. */ - SYSCFG_MEM_MODE_SYSTEM_FLASH = 0x1, - /** FSMC bank 1 (NOR/PSRAM 1 and 2) is mapped at 0x0. */ - SYSCFG_MEM_MODE_FSMC_BANK_1 = 0x2, - /** Embedded SRAM (i.e., not backup SRAM) is mapped at 0x0. */ - SYSCFG_MEM_MODE_SRAM = 0x3, -} syscfg_mem_mode; - - -/** - * @brief Set the memory to be mapped at address 0x00000000. - * - * This function can be used to override the BOOT pin - * configuration. Some restrictions apply; see your chip's reference - * manual for the details. - * - * @param mode Mode to set - * @see syscfg_mem_mode - */ -void syscfg_set_mem_mode(syscfg_mem_mode); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/systick.h b/STM32F3/cores/maple/libmaple/include/libmaple/systick.h deleted file mode 100644 index 551f800..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/systick.h +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/systick.h - * @brief System timer definitions - */ - -#ifndef _LIBMAPLE_SYSTICK_H_ -#define _LIBMAPLE_SYSTICK_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -/** SysTick register map type */ -typedef struct systick_reg_map { - __io uint32 CSR; /**< Control and status register */ - __io uint32 RVR; /**< Reload value register */ - __io uint32 CNT; /**< Current value register ("count") */ - __io uint32 CVR; /**< Calibration value register */ -} systick_reg_map; - -/** SysTick register map base pointer */ -#define SYSTICK_BASE ((struct systick_reg_map*)0xE000E010) - -/* - * Register bit definitions. - */ - -/* Control and status register */ - -#define SYSTICK_CSR_COUNTFLAG BIT(16) -#define SYSTICK_CSR_CLKSOURCE BIT(2) -#define SYSTICK_CSR_CLKSOURCE_EXTERNAL 0 -#define SYSTICK_CSR_CLKSOURCE_CORE BIT(2) -#define SYSTICK_CSR_TICKINT BIT(1) -#define SYSTICK_CSR_TICKINT_PEND BIT(1) -#define SYSTICK_CSR_TICKINT_NO_PEND 0 -#define SYSTICK_CSR_ENABLE BIT(0) -#define SYSTICK_CSR_ENABLE_MULTISHOT BIT(0) -#define SYSTICK_CSR_ENABLE_DISABLED 0 - -/* Calibration value register */ - -#define SYSTICK_CVR_NOREF BIT(31) -#define SYSTICK_CVR_SKEW BIT(30) -#define SYSTICK_CVR_TENMS 0xFFFFFF - -/** System elapsed time, in milliseconds */ -extern volatile uint32 systick_uptime_millis; - -/** - * @brief Returns the system uptime, in milliseconds. - */ -static inline uint32 systick_uptime(void) { - return systick_uptime_millis; -} - - -void systick_init(uint32 reload_val); -void systick_disable(); -void systick_enable(); - -/** - * @brief Returns the current value of the SysTick counter. - */ -static inline uint32 systick_get_count(void) { - return SYSTICK_BASE->CNT; -} - -/** - * @brief Check for underflow. - * - * This function returns 1 if the SysTick timer has counted to 0 since - * the last time it was called. However, any reads of any part of the - * SysTick Control and Status Register SYSTICK_BASE->CSR will - * interfere with this functionality. See the ARM Cortex M3 Technical - * Reference Manual for more details (e.g. Table 8-3 in revision r1p1). - */ -static inline uint32 systick_check_underflow(void) { - return SYSTICK_BASE->CSR & SYSTICK_CSR_COUNTFLAG; -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/timer.h b/STM32F3/cores/maple/libmaple/include/libmaple/timer.h deleted file mode 100644 index 9167f7d..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/timer.h +++ /dev/null @@ -1,1119 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/timer.h - * @author Marti Bolivar - * @brief Timer interface. - */ - -#ifndef _LIBMAPLE_TIMER_H_ -#define _LIBMAPLE_TIMER_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include -#include -#include -#include - -/* - * Register maps - */ - -/** Advanced control timer register map type */ -typedef struct timer_adv_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ - __io uint32 RCR; /**< Repetition counter register */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ - __io uint32 BDTR; /**< Break and dead-time register */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ -} timer_adv_reg_map; - -/* General purpose timer register map type: intentionally omitted. - * - * General purpose timers differ slightly across series, so leave it - * up to the series header to define struct timer_gen_reg_map. */ - -/** Basic timer register map type */ -typedef struct timer_bas_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - const uint32 RESERVED1; /**< Reserved */ - __io uint32 DIER; /**< DMA/interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - const uint32 RESERVED2; /**< Reserved */ - const uint32 RESERVED3; /**< Reserved */ - const uint32 RESERVED4; /**< Reserved */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ -} timer_bas_reg_map; - -/* - * Timer devices - */ - -/** - * @brief Timer register map type. - * - * Just holds a pointer to the correct type of register map, based on - * the timer's type. - */ -typedef union timer_reg_map { - timer_adv_reg_map *adv; /**< Advanced register map */ - timer_gen_reg_map *gen; /**< General purpose register map */ - timer_bas_reg_map *bas; /**< Basic register map */ -} timer_reg_map; - -/** - * @brief Timer type - * - * Type marker for timer_dev. - * - * @see timer_dev - */ -typedef enum timer_type { - TIMER_ADVANCED, /**< Advanced type */ - TIMER_GENERAL, /**< General purpose type */ - TIMER_BASIC, /**< Basic type */ -} timer_type; - -/** Timer device type */ -typedef struct timer_dev { - timer_reg_map regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - timer_type type; /**< Timer's type */ - voidFuncPtr handlers[]; /**< - * Don't touch these. Use these instead: - * @see timer_attach_interrupt() - * @see timer_detach_interrupt() */ -} timer_dev; - -#if STM32_HAVE_TIMER(1) -extern timer_dev *TIMER1; -#endif -#if STM32_HAVE_TIMER(2) -extern timer_dev *TIMER2; -#endif -#if STM32_HAVE_TIMER(3) -extern timer_dev *TIMER3; -#endif -#if STM32_HAVE_TIMER(4) -extern timer_dev *TIMER4; -#endif -#if STM32_HAVE_TIMER(5) -extern timer_dev *TIMER5; -#endif -#if STM32_HAVE_TIMER(6) -extern timer_dev *TIMER6; -#endif -#if STM32_HAVE_TIMER(7) -extern timer_dev *TIMER7; -#endif -#if STM32_HAVE_TIMER(8) -extern timer_dev *TIMER8; -#endif -#if STM32_HAVE_TIMER(9) -extern timer_dev *TIMER9; -#endif -#if STM32_HAVE_TIMER(10) -extern timer_dev *TIMER10; -#endif -#if STM32_HAVE_TIMER(11) -extern timer_dev *TIMER11; -#endif -#if STM32_HAVE_TIMER(12) -extern timer_dev *TIMER12; -#endif -#if STM32_HAVE_TIMER(13) -extern timer_dev *TIMER13; -#endif -#if STM32_HAVE_TIMER(14) -extern timer_dev *TIMER14; -#endif -#if STM32_HAVE_TIMER(15) -extern timer_dev *TIMER15; -#endif -#if STM32_HAVE_TIMER(16) -extern timer_dev *TIMER16; -#endif -#if STM32_HAVE_TIMER(17) -extern timer_dev *TIMER17; -#endif - -/* - * Register bit definitions - */ - -/* Control register 1 (CR1) */ - -#define TIMER_CR1_ARPE_BIT 7 -#define TIMER_CR1_DIR_BIT 4 -#define TIMER_CR1_OPM_BIT 3 -#define TIMER_CR1_URS_BIT 2 -#define TIMER_CR1_UDIS_BIT 1 -#define TIMER_CR1_CEN_BIT 0 - -#define TIMER_CR1_CKD (0x3 << 8) -#define TIMER_CR1_CKD_1TCKINT (0x0 << 8) -#define TIMER_CR1_CKD_2TCKINT (0x1 << 8) -#define TIMER_CR1_CKD_4TICKINT (0x2 << 8) -#define TIMER_CR1_ARPE (1U << TIMER_CR1_ARPE_BIT) -#define TIMER_CR1_CKD_CMS (0x3 << 5) -#define TIMER_CR1_CKD_CMS_EDGE (0x0 << 5) -#define TIMER_CR1_CKD_CMS_CENTER1 (0x1 << 5) -#define TIMER_CR1_CKD_CMS_CENTER2 (0x2 << 5) -#define TIMER_CR1_CKD_CMS_CENTER3 (0x3 << 5) -#define TIMER_CR1_DIR (1U << TIMER_CR1_DIR_BIT) -#define TIMER_CR1_OPM (1U << TIMER_CR1_OPM_BIT) -#define TIMER_CR1_URS (1U << TIMER_CR1_URS_BIT) -#define TIMER_CR1_UDIS (1U << TIMER_CR1_UDIS_BIT) -#define TIMER_CR1_CEN (1U << TIMER_CR1_CEN_BIT) - -/* Control register 2 (CR2) */ - -#define TIMER_CR2_OIS4_BIT 14 -#define TIMER_CR2_OIS3N_BIT 13 -#define TIMER_CR2_OIS3_BIT 12 -#define TIMER_CR2_OIS2N_BIT 11 -#define TIMER_CR2_OIS2_BIT 10 -#define TIMER_CR2_OIS1N_BIT 9 -#define TIMER_CR2_OIS1_BIT 8 -#define TIMER_CR2_TI1S_BIT 7 -#define TIMER_CR2_CCDS_BIT 3 -#define TIMER_CR2_CCUS_BIT 2 -#define TIMER_CR2_CCPC_BIT 0 - -#define TIMER_CR2_OIS4 (1U << TIMER_CR2_OIS4_BIT) -#define TIMER_CR2_OIS3N (1U << TIMER_CR2_OIS3N_BIT) -#define TIMER_CR2_OIS3 (1U << TIMER_CR2_OIS3_BIT) -#define TIMER_CR2_OIS2N (1U << TIMER_CR2_OIS2N_BIT) -#define TIMER_CR2_OIS2 (1U << TIMER_CR2_OIS2_BIT) -#define TIMER_CR2_OIS1N (1U << TIMER_CR2_OIS1N_BIT) -#define TIMER_CR2_OIS1 (1U << TIMER_CR2_OIS1_BIT) -#define TIMER_CR2_TI1S (1U << TIMER_CR2_TI1S_BIT) -#define TIMER_CR2_MMS (0x7 << 4) -#define TIMER_CR2_MMS_RESET (0x0 << 4) -#define TIMER_CR2_MMS_ENABLE (0x1 << 4) -#define TIMER_CR2_MMS_UPDATE (0x2 << 4) -#define TIMER_CR2_MMS_COMPARE_PULSE (0x3 << 4) -#define TIMER_CR2_MMS_COMPARE_OC1REF (0x4 << 4) -#define TIMER_CR2_MMS_COMPARE_OC2REF (0x5 << 4) -#define TIMER_CR2_MMS_COMPARE_OC3REF (0x6 << 4) -#define TIMER_CR2_MMS_COMPARE_OC4REF (0x7 << 4) -#define TIMER_CR2_CCDS (1U << TIMER_CR2_CCDS_BIT) -#define TIMER_CR2_CCUS (1U << TIMER_CR2_CCUS_BIT) -#define TIMER_CR2_CCPC (1U << TIMER_CR2_CCPC_BIT) - -/* Slave mode control register (SMCR) */ - -#define TIMER_SMCR_ETP_BIT 15 -#define TIMER_SMCR_ECE_BIT 14 -#define TIMER_SMCR_MSM_BIT 7 - -#define TIMER_SMCR_ETP (1U << TIMER_SMCR_ETP_BIT) -#define TIMER_SMCR_ECE (1U << TIMER_SMCR_ECE_BIT) -#define TIMER_SMCR_ETPS (0x3 << 12) -#define TIMER_SMCR_ETPS_OFF (0x0 << 12) -#define TIMER_SMCR_ETPS_DIV2 (0x1 << 12) -#define TIMER_SMCR_ETPS_DIV4 (0x2 << 12) -#define TIMER_SMCR_ETPS_DIV8 (0x3 << 12) -#define TIMER_SMCR_ETF (0xF << 12) -#define TIMER_SMCR_MSM (1U << TIMER_SMCR_MSM_BIT) -#define TIMER_SMCR_TS (0x3 << 4) -#define TIMER_SMCR_TS_ITR0 (0x0 << 4) -#define TIMER_SMCR_TS_ITR1 (0x1 << 4) -#define TIMER_SMCR_TS_ITR2 (0x2 << 4) -#define TIMER_SMCR_TS_ITR3 (0x3 << 4) -#define TIMER_SMCR_TS_TI1F_ED (0x4 << 4) -#define TIMER_SMCR_TS_TI1FP1 (0x5 << 4) -#define TIMER_SMCR_TS_TI2FP2 (0x6 << 4) -#define TIMER_SMCR_TS_ETRF (0x7 << 4) -#define TIMER_SMCR_SMS 0x3 -#define TIMER_SMCR_SMS_DISABLED 0x0 -#define TIMER_SMCR_SMS_ENCODER1 0x1 -#define TIMER_SMCR_SMS_ENCODER2 0x2 -#define TIMER_SMCR_SMS_ENCODER3 0x3 -#define TIMER_SMCR_SMS_RESET 0x4 -#define TIMER_SMCR_SMS_GATED 0x5 -#define TIMER_SMCR_SMS_TRIGGER 0x6 -#define TIMER_SMCR_SMS_EXTERNAL 0x7 - -/* DMA/Interrupt enable register (DIER) */ - -#define TIMER_DIER_TDE_BIT 14 -#define TIMER_DIER_COMDE_BIT 13 -#define TIMER_DIER_CC4DE_BIT 12 -#define TIMER_DIER_CC3DE_BIT 11 -#define TIMER_DIER_CC2DE_BIT 10 -#define TIMER_DIER_CC1DE_BIT 9 -#define TIMER_DIER_UDE_BIT 8 -#define TIMER_DIER_BIE_BIT 7 -#define TIMER_DIER_TIE_BIT 6 -#define TIMER_DIER_COMIE_BIT 5 -#define TIMER_DIER_CC4IE_BIT 4 -#define TIMER_DIER_CC3IE_BIT 3 -#define TIMER_DIER_CC2IE_BIT 2 -#define TIMER_DIER_CC1IE_BIT 1 -#define TIMER_DIER_UIE_BIT 0 - -#define TIMER_DIER_TDE (1U << TIMER_DIER_TDE_BIT) -#define TIMER_DIER_COMDE (1U << TIMER_DIER_COMDE_BIT) -#define TIMER_DIER_CC4DE (1U << TIMER_DIER_CC4DE_BIT) -#define TIMER_DIER_CC3DE (1U << TIMER_DIER_CC3DE_BIT) -#define TIMER_DIER_CC2DE (1U << TIMER_DIER_CC2DE_BIT) -#define TIMER_DIER_CC1DE (1U << TIMER_DIER_CC1DE_BIT) -#define TIMER_DIER_UDE (1U << TIMER_DIER_UDE_BIT) -#define TIMER_DIER_BIE (1U << TIMER_DIER_BIE_BIT) -#define TIMER_DIER_TIE (1U << TIMER_DIER_TIE_BIT) -#define TIMER_DIER_COMIE (1U << TIMER_DIER_COMIE_BIT) -#define TIMER_DIER_CC4IE (1U << TIMER_DIER_CC4IE_BIT) -#define TIMER_DIER_CC3IE (1U << TIMER_DIER_CC3IE_BIT) -#define TIMER_DIER_CC2IE (1U << TIMER_DIER_CC2IE_BIT) -#define TIMER_DIER_CC1IE (1U << TIMER_DIER_CC1IE_BIT) -#define TIMER_DIER_UIE (1U << TIMER_DIER_UIE_BIT) - -/* Status register (SR) */ - -#define TIMER_SR_CC4OF_BIT 12 -#define TIMER_SR_CC3OF_BIT 11 -#define TIMER_SR_CC2OF_BIT 10 -#define TIMER_SR_CC1OF_BIT 9 -#define TIMER_SR_BIF_BIT 7 -#define TIMER_SR_TIF_BIT 6 -#define TIMER_SR_COMIF_BIT 5 -#define TIMER_SR_CC4IF_BIT 4 -#define TIMER_SR_CC3IF_BIT 3 -#define TIMER_SR_CC2IF_BIT 2 -#define TIMER_SR_CC1IF_BIT 1 -#define TIMER_SR_UIF_BIT 0 - -#define TIMER_SR_CC4OF (1U << TIMER_SR_CC4OF_BIT) -#define TIMER_SR_CC3OF (1U << TIMER_SR_CC3OF_BIT) -#define TIMER_SR_CC2OF (1U << TIMER_SR_CC2OF_BIT) -#define TIMER_SR_CC1OF (1U << TIMER_SR_CC1OF_BIT) -#define TIMER_SR_BIF (1U << TIMER_SR_BIF_BIT) -#define TIMER_SR_TIF (1U << TIMER_SR_TIF_BIT) -#define TIMER_SR_COMIF (1U << TIMER_SR_COMIF_BIT) -#define TIMER_SR_CC4IF (1U << TIMER_SR_CC4IF_BIT) -#define TIMER_SR_CC3IF (1U << TIMER_SR_CC3IF_BIT) -#define TIMER_SR_CC2IF (1U << TIMER_SR_CC2IF_BIT) -#define TIMER_SR_CC1IF (1U << TIMER_SR_CC1IF_BIT) -#define TIMER_SR_UIF (1U << TIMER_SR_UIF_BIT) - -/* Event generation register (EGR) */ - -#define TIMER_EGR_BG_BIT 7 -#define TIMER_EGR_TG_BIT 6 -#define TIMER_EGR_COMG_BIT 5 -#define TIMER_EGR_CC4G_BIT 4 -#define TIMER_EGR_CC3G_BIT 3 -#define TIMER_EGR_CC2G_BIT 2 -#define TIMER_EGR_CC1G_BIT 1 -#define TIMER_EGR_UG_BIT 0 - -#define TIMER_EGR_BG (1U << TIMER_EGR_BG_BIT) -#define TIMER_EGR_TG (1U << TIMER_EGR_TG_BIT) -#define TIMER_EGR_COMG (1U << TIMER_EGR_COMG_BIT) -#define TIMER_EGR_CC4G (1U << TIMER_EGR_CC4G_BIT) -#define TIMER_EGR_CC3G (1U << TIMER_EGR_CC3G_BIT) -#define TIMER_EGR_CC2G (1U << TIMER_EGR_CC2G_BIT) -#define TIMER_EGR_CC1G (1U << TIMER_EGR_CC1G_BIT) -#define TIMER_EGR_UG (1U << TIMER_EGR_UG_BIT) - -/* Capture/compare mode registers, common values */ - -#define TIMER_CCMR_CCS_OUTPUT 0x0 -#define TIMER_CCMR_CCS_INPUT_TI1 0x1 -#define TIMER_CCMR_CCS_INPUT_TI2 0x2 -#define TIMER_CCMR_CCS_INPUT_TRC 0x3 - -/* Capture/compare mode register 1 (CCMR1) */ - -#define TIMER_CCMR1_OC2CE_BIT 15 -#define TIMER_CCMR1_OC2PE_BIT 11 -#define TIMER_CCMR1_OC2FE_BIT 10 -#define TIMER_CCMR1_OC1CE_BIT 7 -#define TIMER_CCMR1_OC1PE_BIT 3 -#define TIMER_CCMR1_OC1FE_BIT 2 - -#define TIMER_CCMR1_OC2CE (1U << TIMER_CCMR1_OC2CE_BIT) -#define TIMER_CCMR1_OC2M (0x3 << 12) -#define TIMER_CCMR1_IC2F (0xF << 12) -#define TIMER_CCMR1_OC2PE (1U << TIMER_CCMR1_OC2PE_BIT) -#define TIMER_CCMR1_OC2FE (1U << TIMER_CCMR1_OC2FE_BIT) -#define TIMER_CCMR1_IC2PSC (0x3 << 10) -#define TIMER_CCMR1_CC2S (0x3 << 8) -#define TIMER_CCMR1_CC2S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) -#define TIMER_CCMR1_CC2S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) -#define TIMER_CCMR1_CC2S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) -#define TIMER_CCMR1_CC2S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) -#define TIMER_CCMR1_OC1CE (1U << TIMER_CCMR1_OC1CE_BIT) -#define TIMER_CCMR1_OC1M (0x3 << 4) -#define TIMER_CCMR1_IC1F (0xF << 4) -#define TIMER_CCMR1_OC1PE (1U << TIMER_CCMR1_OC1PE_BIT) -#define TIMER_CCMR1_OC1FE (1U << TIMER_CCMR1_OC1FE_BIT) -#define TIMER_CCMR1_IC1PSC (0x3 << 2) -#define TIMER_CCMR1_CC1S 0x3 -#define TIMER_CCMR1_CC1S_OUTPUT TIMER_CCMR_CCS_OUTPUT -#define TIMER_CCMR1_CC1S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 -#define TIMER_CCMR1_CC1S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 -#define TIMER_CCMR1_CC1S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC - -/* Capture/compare mode register 2 (CCMR2) */ - -#define TIMER_CCMR2_OC4CE_BIT 15 -#define TIMER_CCMR2_OC4PE_BIT 11 -#define TIMER_CCMR2_OC4FE_BIT 10 -#define TIMER_CCMR2_OC3CE_BIT 7 -#define TIMER_CCMR2_OC3PE_BIT 3 -#define TIMER_CCMR2_OC3FE_BIT 2 - -#define TIMER_CCMR2_OC4CE (1U << TIMER_CCMR2_OC4CE_BIT) -#define TIMER_CCMR2_OC4M (0x3 << 12) -#define TIMER_CCMR2_IC4F (0xF << 12) -#define TIMER_CCMR2_OC4PE (1U << TIMER_CCMR2_OC4PE_BIT) -#define TIMER_CCMR2_OC4FE (1U << TIMER_CCMR2_OC4FE_BIT) -#define TIMER_CCMR2_IC4PSC (0x3 << 10) -#define TIMER_CCMR2_CC4S (0x3 << 8) -#define TIMER_CCMR2_CC4S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) -#define TIMER_CCMR2_CC4S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) -#define TIMER_CCMR2_CC4S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) -#define TIMER_CCMR2_CC4S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) -#define TIMER_CCMR2_OC3CE (1U << TIMER_CCMR2_OC3CE_BIT) -#define TIMER_CCMR2_OC3M (0x3 << 4) -#define TIMER_CCMR2_IC3F (0xF << 4) -#define TIMER_CCMR2_OC3PE (1U << TIMER_CCMR2_OC3PE_BIT) -#define TIMER_CCMR2_OC3FE (1U << TIMER_CCMR2_OC3FE_BIT) -#define TIMER_CCMR2_IC3PSC (0x3 << 2) -#define TIMER_CCMR2_CC3S 0x3 -#define TIMER_CCMR2_CC3S_OUTPUT TIMER_CCMR_CCS_OUTPUT -#define TIMER_CCMR2_CC3S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 -#define TIMER_CCMR2_CC3S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 -#define TIMER_CCMR2_CC3S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC - -/* Capture/compare enable register (CCER) */ - -#define TIMER_CCER_CC4P_BIT 13 -#define TIMER_CCER_CC4E_BIT 12 -#define TIMER_CCER_CC3NP_BIT 11 -#define TIMER_CCER_CC3NE_BIT 10 -#define TIMER_CCER_CC3P_BIT 9 -#define TIMER_CCER_CC3E_BIT 8 -#define TIMER_CCER_CC2NP_BIT 7 -#define TIMER_CCER_CC2NE_BIT 6 -#define TIMER_CCER_CC2P_BIT 5 -#define TIMER_CCER_CC2E_BIT 4 -#define TIMER_CCER_CC1NP_BIT 3 -#define TIMER_CCER_CC1NE_BIT 2 -#define TIMER_CCER_CC1P_BIT 1 -#define TIMER_CCER_CC1E_BIT 0 - -#define TIMER_CCER_CC4P (1U << TIMER_CCER_CC4P_BIT) -#define TIMER_CCER_CC4E (1U << TIMER_CCER_CC4E_BIT) -#define TIMER_CCER_CC3NP (1U << TIMER_CCER_CC3NP_BIT) -#define TIMER_CCER_CC3NE (1U << TIMER_CCER_CC3NE_BIT) -#define TIMER_CCER_CC3P (1U << TIMER_CCER_CC3P_BIT) -#define TIMER_CCER_CC3E (1U << TIMER_CCER_CC3E_BIT) -#define TIMER_CCER_CC2NP (1U << TIMER_CCER_CC2NP_BIT) -#define TIMER_CCER_CC2NE (1U << TIMER_CCER_CC2NE_BIT) -#define TIMER_CCER_CC2P (1U << TIMER_CCER_CC2P_BIT) -#define TIMER_CCER_CC2E (1U << TIMER_CCER_CC2E_BIT) -#define TIMER_CCER_CC1NP (1U << TIMER_CCER_CC1NP_BIT) -#define TIMER_CCER_CC1NE (1U << TIMER_CCER_CC1NE_BIT) -#define TIMER_CCER_CC1P (1U << TIMER_CCER_CC1P_BIT) -#define TIMER_CCER_CC1E (1U << TIMER_CCER_CC1E_BIT) - -/* Break and dead-time register (BDTR) */ - -#define TIMER_BDTR_MOE_BIT 15 -#define TIMER_BDTR_AOE_BIT 14 -#define TIMER_BDTR_BKP_BIT 13 -#define TIMER_BDTR_BKE_BIT 12 -#define TIMER_BDTR_OSSR_BIT 11 -#define TIMER_BDTR_OSSI_BIT 10 - -#define TIMER_BDTR_MOE (1U << TIMER_BDTR_MOE_BIT) -#define TIMER_BDTR_AOE (1U << TIMER_BDTR_AOE_BIT) -#define TIMER_BDTR_BKP (1U << TIMER_BDTR_BKP_BIT) -#define TIMER_BDTR_BKE (1U << TIMER_BDTR_BKE_BIT) -#define TIMER_BDTR_OSSR (1U << TIMER_BDTR_OSSR_BIT) -#define TIMER_BDTR_OSSI (1U << TIMER_BDTR_OSSI_BIT) -#define TIMER_BDTR_LOCK (0x3 << 8) -#define TIMER_BDTR_LOCK_OFF (0x0 << 8) -#define TIMER_BDTR_LOCK_LEVEL1 (0x1 << 8) -#define TIMER_BDTR_LOCK_LEVEL2 (0x2 << 8) -#define TIMER_BDTR_LOCK_LEVEL3 (0x3 << 8) -#define TIMER_BDTR_DTG 0xFF - -/* DMA control register (DCR) */ - -#define TIMER_DCR_DBL (0x1F << 8) -#define TIMER_DCR_DBL_1_XFER (0x0 << 8) -#define TIMER_DCR_DBL_2_XFER (0x1 << 8) -#define TIMER_DCR_DBL_3_XFER (0x2 << 8) -#define TIMER_DCR_DBL_4_XFER (0x3 << 8) -#define TIMER_DCR_DBL_5_XFER (0x4 << 8) -#define TIMER_DCR_DBL_6_XFER (0x5 << 8) -#define TIMER_DCR_DBL_7_XFER (0x6 << 8) -#define TIMER_DCR_DBL_8_XFER (0x7 << 8) -#define TIMER_DCR_DBL_9_XFER (0x8 << 8) -#define TIMER_DCR_DBL_10_XFER (0x9 << 8) -#define TIMER_DCR_DBL_11_XFER (0xA << 8) -#define TIMER_DCR_DBL_12_XFER (0xB << 8) -#define TIMER_DCR_DBL_13_XFER (0xC << 8) -#define TIMER_DCR_DBL_14_XFER (0xD << 8) -#define TIMER_DCR_DBL_15_XFER (0xE << 8) -#define TIMER_DCR_DBL_16_XFER (0xF << 8) -#define TIMER_DCR_DBL_17_XFER (0x10 << 8) -#define TIMER_DCR_DBL_18_XFER (0x11 << 8) -#define TIMER_DCR_DBA 0x1F -#define TIMER_DCR_DBA_CR1 0x0 -#define TIMER_DCR_DBA_CR2 0x1 -#define TIMER_DCR_DBA_SMCR 0x2 -#define TIMER_DCR_DBA_DIER 0x3 -#define TIMER_DCR_DBA_SR 0x4 -#define TIMER_DCR_DBA_EGR 0x5 -#define TIMER_DCR_DBA_CCMR1 0x6 -#define TIMER_DCR_DBA_CCMR2 0x7 -#define TIMER_DCR_DBA_CCER 0x8 -#define TIMER_DCR_DBA_CNT 0x9 -#define TIMER_DCR_DBA_PSC 0xA -#define TIMER_DCR_DBA_ARR 0xB -#define TIMER_DCR_DBA_RCR 0xC -#define TIMER_DCR_DBA_CCR1 0xD -#define TIMER_DCR_DBA_CCR2 0xE -#define TIMER_DCR_DBA_CCR3 0xF -#define TIMER_DCR_DBA_CCR4 0x10 -#define TIMER_DCR_DBA_BDTR 0x11 -#define TIMER_DCR_DBA_DCR 0x12 -#define TIMER_DCR_DBA_DMAR 0x13 - -/* - * Convenience routines - */ - -/** - * @brief Used to configure the behavior of a timer channel. - * - * Be careful: not all timers can be configured in every mode. - */ -typedef enum timer_mode { - /** - * The timer stops counting, channel interrupts are detached, and - * no state changes are output. */ - TIMER_DISABLED, - - /** PWM output. */ - TIMER_PWM, - - /* TIMER_PWM_CENTER_ALIGNED, TODO: Center-aligned PWM output mode. */ - - /** - * The timer counts from 0 to its reload value repeatedly; every - * time the counter value reaches one of the channel compare - * values, the corresponding interrupt is fired. */ - TIMER_OUTPUT_COMPARE, - - /* TIMER_INPUT_CAPTURE, TODO: In this mode, the timer can measure the - * pulse lengths of input signals */ - /* TIMER_ONE_PULSE, TODO: In this mode, the timer can generate a single - * pulse on a GPIO pin for a specified amount of - * time. */ -} timer_mode; - -/** Timer channel numbers */ -typedef enum timer_channel { - TIMER_CH1 = 1, /**< Channel 1 */ - TIMER_CH2 = 2, /**< Channel 2 */ - TIMER_CH3 = 3, /**< Channel 3 */ - TIMER_CH4 = 4 /**< Channel 4 */ -} timer_channel; - -/* - * Note: Don't require timer_channel arguments! We want to be able to say - * - * for (int channel = 1; channel <= 4; channel++) { - * ... - * } - * - * without the compiler yelling at us. - */ - -void timer_init(timer_dev *dev); -void timer_disable(timer_dev *dev); -void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode); -void timer_foreach(void (*fn)(timer_dev*)); -int timer_has_cc_channel(timer_dev *dev, uint8 channel); - -/** - * @brief Timer interrupt number. - * - * Not all timers support all of these values. All timers support - * TIMER_UPDATE_INTERRUPT. "General purpose" timers can be a special - * nuisance in this regard, as they individually support different - * subsets of the available interupts. Consult your target's reference - * manual for the details. - */ -typedef enum timer_interrupt_id { - TIMER_UPDATE_INTERRUPT, /**< Update interrupt. */ - TIMER_CC1_INTERRUPT, /**< Capture/compare 1 interrupt. */ - TIMER_CC2_INTERRUPT, /**< Capture/compare 2 interrupt. */ - TIMER_CC3_INTERRUPT, /**< Capture/compare 3 interrupt. */ - TIMER_CC4_INTERRUPT, /**< Capture/compare 4 interrupt. */ - TIMER_COM_INTERRUPT, /**< COM interrupt. */ - TIMER_TRG_INTERRUPT, /**< Trigger interrupt. */ - TIMER_BREAK_INTERRUPT, /**< Break interrupt. */ -} timer_interrupt_id; - -void timer_attach_interrupt(timer_dev *dev, - uint8 interrupt, - voidFuncPtr handler); -void timer_detach_interrupt(timer_dev *dev, uint8 interrupt); - -/** - * Initialize all timer devices on the chip. - */ -static inline void timer_init_all(void) { - timer_foreach(timer_init); -} - -/** - * Disables all timers on the device. - */ -static inline void timer_disable_all(void) { - timer_foreach(timer_disable); -} - -/** - * @brief Stop a timer's counter from changing. - * - * Does not affect the timer's mode or other settings. - * - * @param dev Device whose counter to pause. - */ -static inline void timer_pause(timer_dev *dev) { - *bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 0; -} - -/** - * @brief Start a timer's counter. - * - * Does not affect the timer's mode or other settings. - * - * @param dev Device whose counter to resume - */ -static inline void timer_resume(timer_dev *dev) { - *bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 1; -} - -/** - * @brief Returns the timer's counter value. - * - * This value is likely to be inaccurate if the counter is running - * with a low prescaler. - * - * @param dev Timer whose counter to return - */ -static inline uint16 timer_get_count(timer_dev *dev) { - return (uint16)(dev->regs).bas->CNT; -} - -/** - * @brief Sets the counter value for the given timer. - * @param dev Timer whose counter to set - * @param value New counter value - */ -static inline void timer_set_count(timer_dev *dev, uint16 value) { - (dev->regs).bas->CNT = value; -} - -/** - * @brief Returns the given timer's prescaler. - * - * Note that if the timer's prescaler is set (e.g. via - * timer_set_prescaler() or accessing a TIMx_PSC register), the value - * returned by this function will reflect the new setting, but the - * timer's counter will only reflect the new prescaler at the next - * update event. - * - * @param dev Timer whose prescaler to return - * @see timer_generate_update() - */ -static inline uint16 timer_get_prescaler(timer_dev *dev) { - return (uint16)(dev->regs).bas->PSC; -} - -/** - * @brief Set a timer's prescale value. - * - * Divides the input clock by (PSC+1). The new value will not take - * effect until the next update event. - * - * @param dev Timer whose prescaler to set - * @param psc New prescaler value - * @see timer_generate_update() - */ -static inline void timer_set_prescaler(timer_dev *dev, uint16 psc) { - (dev->regs).bas->PSC = psc; -} - -/** - * @brief Returns a timer's reload value. - * @param dev Timer whose reload value to return - */ -static inline uint16 timer_get_reload(timer_dev *dev) { - return (uint16)(dev->regs).bas->ARR; -} - -/** - * @brief Set a timer's reload value. - * @param dev Timer whose reload value to set - * @param arr New reload value to use. Takes effect at next update event. - * @see timer_generate_update() - */ -static inline void timer_set_reload(timer_dev *dev, uint16 arr) { - (dev->regs).bas->ARR = arr; -} - -/** - * @brief Get the compare value for the given timer channel. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel whose compare value to get. - */ -static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) { - __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); - return *ccr; -} - -/** - * @brief Set the compare value for the given timer channel. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel whose compare value to set. - * @param value New compare value. - */ -static inline void timer_set_compare(timer_dev *dev, - uint8 channel, - uint16 value) { - __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); - *ccr = value; -} - -/** - * @brief Generate an update event for the given timer. - * - * Normally, this will cause the prescaler and auto-reload values in - * the PSC and ARR registers to take immediate effect. However, this - * function will do nothing if the UDIS bit is set in the timer's CR1 - * register (UDIS is cleared by default). - * - * @param dev Timer device to generate an update for. - */ -static inline void timer_generate_update(timer_dev *dev) { - *bb_perip(&(dev->regs).bas->EGR, TIMER_EGR_UG_BIT) = 1; -} - -/** - * @brief Enable a timer's trigger DMA request - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL - */ -static inline void timer_dma_enable_trg_req(timer_dev *dev) { - *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 1; -} - -/** - * @brief Disable a timer's trigger DMA request - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL - */ -static inline void timer_dma_disable_trg_req(timer_dev *dev) { - *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 0; -} - -/** - * @brief Enable a timer channel's DMA request. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL - * @param channel Channel whose DMA request to enable. - */ -static inline void timer_dma_enable_req(timer_dev *dev, uint8 channel) { - *bb_perip(&(dev->regs).gen->DIER, channel + 8) = 1; -} - -/** - * @brief Disable a timer channel's DMA request. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel whose DMA request to disable. - */ -static inline void timer_dma_disable_req(timer_dev *dev, uint8 channel) { - *bb_perip(&(dev->regs).gen->DIER, channel + 8) = 0; -} - -/** - * @brief Enable a timer interrupt. - * @param dev Timer device. - * @param interrupt Interrupt number to enable; this may be any - * timer_interrupt_id value appropriate for the timer. - * @see timer_interrupt_id - * @see timer_channel - */ -static inline void timer_enable_irq(timer_dev *dev, uint8 interrupt) { - *bb_perip(&(dev->regs).adv->DIER, interrupt) = 1; -} - -/** - * @brief Disable a timer interrupt. - * @param dev Timer device. - * @param interrupt Interrupt number to disable; this may be any - * timer_interrupt_id value appropriate for the timer. - * @see timer_interrupt_id - * @see timer_channel - */ -static inline void timer_disable_irq(timer_dev *dev, uint8 interrupt) { - *bb_perip(&(dev->regs).adv->DIER, interrupt) = 0; -} - -/** - * @brief Enable a timer channel's capture/compare signal. - * - * If the channel is configured as output, the corresponding output - * compare signal will be output on the corresponding output pin. If - * the channel is configured as input, enables capture of the counter - * value into the input capture/compare register. - * - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel to enable, from 1 to 4. - */ -static inline void timer_cc_enable(timer_dev *dev, uint8 channel) { - *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1)) = 1; -} - -/** - * @brief Disable a timer channel's output compare or input capture signal. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel to disable, from 1 to 4. - * @see timer_cc_enable() - */ -static inline void timer_cc_disable(timer_dev *dev, uint8 channel) { - *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1)) = 0; -} - -/** - * @brief Get a channel's capture/compare output polarity - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel whose capture/compare output polarity to get. - * @return Polarity, either 0 or 1. - * @see timer_cc_set_polarity() - */ -static inline uint8 timer_cc_get_pol(timer_dev *dev, uint8 channel) { - return *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1) + 1); -} - -/** - * @brief Set a timer channel's capture/compare output polarity. - * - * If the timer channel is configured as output: polarity == 0 means - * the output channel will be active high; polarity == 1 means active - * low. - * - * If the timer channel is configured as input: polarity == 0 means - * capture is done on the rising edge of ICn; when used as an external - * trigger, ICn is non-inverted. polarity == 1 means capture is done - * on the falling edge of ICn; when used as an external trigger, ICn - * is inverted. - * - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel whose capture/compare output polarity to set. - * @param pol New polarity, 0 or 1. - */ -static inline void timer_cc_set_pol(timer_dev *dev, uint8 channel, uint8 pol) { - *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1) + 1) = pol; -} - -/** - * @brief Get a timer's DMA burst length. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @return Number of transfers per read or write to timer DMA register, - * from 1 to 18. - */ -static inline uint8 timer_dma_get_burst_len(timer_dev *dev) { - uint32 dbl = ((dev->regs).gen->DCR & TIMER_DCR_DBL) >> 8; - return dbl + 1; /* 0 means 1 transfer, etc. */ -} - -/** - * @brief Set a timer's DMA burst length. - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param length DMA burst length; i.e., number of DMA transfers per - * read/write to timer DMA register, from 1 to 18. - */ -static inline void timer_dma_set_burst_len(timer_dev *dev, uint8 length) { - uint32 tmp = (dev->regs).gen->DCR; - tmp &= ~TIMER_DCR_DBL; - tmp |= (length - 1) << 8; - (dev->regs).gen->DCR = tmp; -} - -/** - * @brief Timer DMA base address. - * - * Defines the base address for DMA transfers. - */ -typedef enum timer_dma_base_addr { - /** Base is control register 1 */ - TIMER_DMA_BASE_CR1 = TIMER_DCR_DBA_CR1, - /** Base is control register 2 */ - TIMER_DMA_BASE_CR2 = TIMER_DCR_DBA_CR2, - /** Base is slave mode control register */ - TIMER_DMA_BASE_SMCR = TIMER_DCR_DBA_SMCR, - /** Base is DMA interrupt enable register */ - TIMER_DMA_BASE_DIER = TIMER_DCR_DBA_DIER, - /** Base is status register */ - TIMER_DMA_BASE_SR = TIMER_DCR_DBA_SR, - /** Base is event generation register */ - TIMER_DMA_BASE_EGR = TIMER_DCR_DBA_EGR, - /** Base is capture/compare mode register 1 */ - TIMER_DMA_BASE_CCMR1 = TIMER_DCR_DBA_CCMR1, - /** Base is capture/compare mode register 2 */ - TIMER_DMA_BASE_CCMR2 = TIMER_DCR_DBA_CCMR2, - /** Base is capture/compare enable register */ - TIMER_DMA_BASE_CCER = TIMER_DCR_DBA_CCER, - /** Base is counter */ - TIMER_DMA_BASE_CNT = TIMER_DCR_DBA_CNT, - /** Base is prescaler */ - TIMER_DMA_BASE_PSC = TIMER_DCR_DBA_PSC, - /** Base is auto-reload register */ - TIMER_DMA_BASE_ARR = TIMER_DCR_DBA_ARR, - /** Base is repetition counter register */ - TIMER_DMA_BASE_RCR = TIMER_DCR_DBA_RCR, - /** Base is capture/compare register 1 */ - TIMER_DMA_BASE_CCR1 = TIMER_DCR_DBA_CCR1, - /** Base is capture/compare register 2 */ - TIMER_DMA_BASE_CCR2 = TIMER_DCR_DBA_CCR2, - /** Base is capture/compare register 3 */ - TIMER_DMA_BASE_CCR3 = TIMER_DCR_DBA_CCR3, - /** Base is capture/compare register 4 */ - TIMER_DMA_BASE_CCR4 = TIMER_DCR_DBA_CCR4, - /** Base is break and dead-time register */ - TIMER_DMA_BASE_BDTR = TIMER_DCR_DBA_BDTR, - /** Base is DMA control register */ - TIMER_DMA_BASE_DCR = TIMER_DCR_DBA_DCR, - /** Base is DMA address for full transfer */ - TIMER_DMA_BASE_DMAR = TIMER_DCR_DBA_DMAR, -} timer_dma_base_addr; - -/** - * @brief Get the timer's DMA base address. - * - * Some restrictions apply; see the reference manual for your chip. - * - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @return DMA base address - */ -static inline timer_dma_base_addr timer_dma_get_base_addr(timer_dev *dev) { - uint32 dcr = (dev->regs).gen->DCR; - return (timer_dma_base_addr)(dcr & TIMER_DCR_DBA); -} - -/** - * @brief Set the timer's DMA base address. - * - * Some restrictions apply; see the reference manual for your chip. - * - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param dma_base DMA base address. - */ -static inline void timer_dma_set_base_addr(timer_dev *dev, - timer_dma_base_addr dma_base) { - uint32 tmp = (dev->regs).gen->DCR; - tmp &= ~TIMER_DCR_DBA; - tmp |= dma_base; - (dev->regs).gen->DCR = tmp; -} - -/** - * Timer output compare modes. - */ -typedef enum timer_oc_mode { - /** - * Frozen: comparison between output compare register and counter - * has no effect on the outputs. */ - TIMER_OC_MODE_FROZEN = 0 << 4, - /** - * OCxREF signal is forced high when the count matches the channel - * capture/compare register. */ - TIMER_OC_MODE_ACTIVE_ON_MATCH = 1 << 4, - /** - * OCxREF signal is forced low when the counter matches the - * channel capture/compare register. */ - TIMER_OC_MODE_INACTIVE_ON_MATCH = 2 << 4, - /** - * OCxREF toggles when counter matches the channel capture/compare - * register. */ - TIMER_OC_MODE_TOGGLE = 3 << 4, - /** OCxREF is forced low. */ - TIMER_OC_MODE_FORCE_INACTIVE = 4 << 4, - /** OCxREF is forced high. */ - TIMER_OC_MODE_FORCE_ACTIVE = 5 << 4, - /** - * PWM mode 1. In upcounting, channel is active as long as count - * is less than channel capture/compare register, else inactive. - * In downcounting, channel is inactive as long as count exceeds - * capture/compare register, else active. */ - TIMER_OC_MODE_PWM_1 = 6 << 4, - /** - * PWM mode 2. In upcounting, channel is inactive as long as count - * is less than capture/compare register, else active. In - * downcounting, channel is active as long as count exceeds - * capture/compare register, else inactive. */ - TIMER_OC_MODE_PWM_2 = 7 << 4, -} timer_oc_mode; - -/** - * Timer output compare mode flags. - * @see timer_oc_set_mode() - */ -typedef enum timer_oc_mode_flags { - TIMER_OC_CE = 1U << 7, /**< Output compare clear enable. */ - TIMER_OC_PE = 1U << 3, /**< Output compare preload enable. */ - TIMER_OC_FE = 1U << 2, /**< Output compare fast enable. */ -} timer_oc_mode_flags; - -/** - * @brief Configure a channel's output compare mode. - * - * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param channel Channel to configure in output compare mode. - * @param mode Timer mode to set. - * @param flags OR of timer_oc_mode_flags. - * @see timer_oc_mode - * @see timer_oc_mode_flags - */ -static inline void timer_oc_set_mode(timer_dev *dev, - uint8 channel, - timer_oc_mode mode, - uint8 flags) { - /* channel == 1,2 -> CCMR1; channel == 3,4 -> CCMR2 */ - __io uint32 *ccmr = &(dev->regs).gen->CCMR1 + (((channel - 1) >> 1) & 1); - /* channel == 1,3 -> shift = 0, channel == 2,4 -> shift = 8 */ - uint8 shift = 8 * (1 - (channel & 1)); - - uint32 tmp = *ccmr; - tmp &= ~(0xFF << shift); - tmp |= (mode | flags | TIMER_CCMR_CCS_OUTPUT) << shift; - *ccmr = tmp; -} - -/* - * Old, erroneous bit definitions from previous releases, kept for - * backwards compatibility: - */ - -/** Deprecated. Use TIMER_CCMR1_CC4S_OUTPUT instead. */ -#define TIMER_CCMR1_CC4S_OUTPUT TIMER_CCMR2_CC4S_OUTPUT -/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI1 instead. */ -#define TIMER_CCMR1_CC4S_INPUT_TI1 TIMER_CCMR2_CC4S_INPUT_TI1 -/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI2 instead. */ -#define TIMER_CCMR1_CC4S_INPUT_TI2 TIMER_CCMR2_CC4S_INPUT_TI2 -/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TRC instead. */ -#define TIMER_CCMR1_CC4S_INPUT_TRC TIMER_CCMR2_CC4S_INPUT_TRC -/** Deprecated. Use TIMER_CCMR2_IC4F instead. */ -#define TIMER_CCMR2_IC2F TIMER_CCMR2_IC4F -/** Deprecated. Use TIMER_CCMR2_IC4PSC instead. */ -#define TIMER_CCMR2_IC2PSC TIMER_CCMR2_IC4PSC -/** Deprecated. Use TIMER_CCMR2_IC3F instead. */ -#define TIMER_CCMR2_IC1F TIMER_CCMR2_IC3F -/** Deprecated. Use TIMER_CCMR2_IC3PSC instead. */ -#define TIMER_CCMR2_IC1PSC TIMER_CCMR2_IC3PSC -/** Deprecated. Use TIMER_CCMR1_CC3S_OUTPUT instead. */ -#define TIMER_CCMR1_CC3S_OUTPUT TIMER_CCMR2_CC3S_OUTPUT -/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI1 instead. */ -#define TIMER_CCMR1_CC3S_INPUT_TI1 TIMER_CCMR2_CC3S_INPUT_TI1 -/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI2 instead. */ -#define TIMER_CCMR1_CC3S_INPUT_TI2 TIMER_CCMR2_CC3S_INPUT_TI2 -/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TRC instead. */ -#define TIMER_CCMR1_CC3S_INPUT_TRC TIMER_CCMR2_CC3S_INPUT_TRC - -/** Deprecated. Use TIMER_DCR_DBL_1_XFER instead. */ -#define TIMER_DCR_DBL_1BYTE TIMER_DCR_DBL_1_XFER -/** Deprecated. Use TIMER_DCR_DBL_2_XFER instead. */ -#define TIMER_DCR_DBL_2BYTE TIMER_DCR_DBL_2_XFER -/** Deprecated. Use TIMER_DCR_DBL_3_XFER instead. */ -#define TIMER_DCR_DBL_3BYTE TIMER_DCR_DBL_3_XFER -/** Deprecated. Use TIMER_DCR_DBL_4_XFER instead. */ -#define TIMER_DCR_DBL_4BYTE TIMER_DCR_DBL_4_XFER -/** Deprecated. Use TIMER_DCR_DBL_5_XFER instead. */ -#define TIMER_DCR_DBL_5BYTE TIMER_DCR_DBL_5_XFER -/** Deprecated. Use TIMER_DCR_DBL_6_XFER instead. */ -#define TIMER_DCR_DBL_6BYTE TIMER_DCR_DBL_6_XFER -/** Deprecated. Use TIMER_DCR_DBL_7_XFER instead. */ -#define TIMER_DCR_DBL_7BYTE TIMER_DCR_DBL_7_XFER -/** Deprecated. Use TIMER_DCR_DBL_8_XFER instead. */ -#define TIMER_DCR_DBL_8BYTE TIMER_DCR_DBL_8_XFER -/** Deprecated. Use TIMER_DCR_DBL_9_XFER instead. */ -#define TIMER_DCR_DBL_9BYTE TIMER_DCR_DBL_9_XFER -/** Deprecated. Use TIMER_DCR_DBL_10_XFER instead. */ -#define TIMER_DCR_DBL_10BYTE TIMER_DCR_DBL_10_XFER -/** Deprecated. Use TIMER_DCR_DBL_11_XFER instead. */ -#define TIMER_DCR_DBL_11BYTE TIMER_DCR_DBL_11_XFER -/** Deprecated. Use TIMER_DCR_DBL_12_XFER instead. */ -#define TIMER_DCR_DBL_12BYTE TIMER_DCR_DBL_12_XFER -/** Deprecated. Use TIMER_DCR_DBL_13_XFER instead. */ -#define TIMER_DCR_DBL_13BYTE TIMER_DCR_DBL_13_XFER -/** Deprecated. Use TIMER_DCR_DBL_14_XFER instead. */ -#define TIMER_DCR_DBL_14BYTE TIMER_DCR_DBL_14_XFER -/** Deprecated. Use TIMER_DCR_DBL_15_XFER instead. */ -#define TIMER_DCR_DBL_15BYTE TIMER_DCR_DBL_15_XFER -/** Deprecated. Use TIMER_DCR_DBL_16_XFER instead. */ -#define TIMER_DCR_DBL_16BYTE TIMER_DCR_DBL_16_XFER -/** Deprecated. Use TIMER_DCR_DBL_17_XFER instead. */ -#define TIMER_DCR_DBL_17BYTE TIMER_DCR_DBL_17_XFER -/** Deprecated. Use TIMER_DCR_DBL_18_XFER instead. */ -#define TIMER_DCR_DBL_18BYTE TIMER_DCR_DBL_18_XFER - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/usart.h b/STM32F3/cores/maple/libmaple/include/libmaple/usart.h deleted file mode 100644 index 82b1b7d..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/usart.h +++ /dev/null @@ -1,464 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/usart.h - * @author Marti Bolivar , - * Perry Hung , - * F3-port by Hanspeter Portner - * @brief USART definitions and prototypes - */ - -#ifndef _LIBMAPLE_USART_H_ -#define _LIBMAPLE_USART_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include -#include -#include -#include -#include - -/* - * Register bit definitions - */ - -/* Status register */ - -/** Line break detection bit */ -#define USART_SR_LBD_BIT 8 -/** Transmit data register empty bit */ -#define USART_SR_TXE_BIT 7 -/** Transmission complete bit */ -#define USART_SR_TC_BIT 6 -/** Read data register not empty bit */ -#define USART_SR_RXNE_BIT 5 -/** IDLE line detected bit */ -#define USART_SR_IDLE_BIT 4 -/** Overrun error bit */ -#define USART_SR_ORE_BIT 3 -/** Noise error bit */ -#define USART_SR_NE_BIT 2 -/** - * @brief Synonym for USART_SR_NE_BIT. - * - * Some series (e.g. STM32F2) use "NF" for "noise flag" instead of the - * original "NE" for "noise error". The meaning of the bit is - * unchanged, but the NF flag can be disabled when the line is - * noise-free. - * - * @see USART_SR_NE_BIT - */ -#define USART_SR_NF_BIT USART_SR_NE_BIT -/** Framing error bit */ -#define USART_SR_FE_BIT 1 -/** Parity error bit */ -#define USART_SR_PE_BIT 0 - -/** Line break detected mask */ -#define USART_SR_LBD BIT(USART_SR_LBD_BIT) -/** Transmit data register empty mask */ -#define USART_SR_TXE BIT(USART_SR_TXE_BIT) -/** Transmission complete mask */ -#define USART_SR_TC BIT(USART_SR_TC_BIT) -/** Read data register not empty mask */ -#define USART_SR_RXNE BIT(USART_SR_RXNE_BIT) -/** IDLE line detected mask */ -#define USART_SR_IDLE BIT(USART_SR_IDLE_BIT) -/** Overrun error mask */ -#define USART_SR_ORE BIT(USART_SR_ORE_BIT) -/** Noise error mask */ -#define USART_SR_NE BIT(USART_SR_NE_BIT) -/** - * @brief Synonym for USART_SR_NE. - * @see USART_SR_NF_BIT - */ -#define USART_SR_NF USART_SR_NE -/** Framing error mask */ -#define USART_SR_FE BIT(USART_SR_FE_BIT) -/** Parity error mask */ -#define USART_SR_PE BIT(USART_SR_PE_BIT) - -/* Data register */ - -/** Data register data value mask */ -#define USART_DR_DR 0xFF - -/* Baud rate register */ - -/** Mantissa of USARTDIV mask */ -#define USART_BRR_DIV_MANTISSA (0xFFF << 4) -/** Fraction of USARTDIV mask */ -#define USART_BRR_DIV_FRACTION 0xF - -/* Control register 1 */ - -/** Word length bit */ -#define USART_CR1_M_BIT 12 -/** Wakeup method bit */ -#define USART_CR1_WAKE_BIT 11 -/** Parity control enable bit */ -#define USART_CR1_PCE_BIT 10 -/** Parity selection bit */ -#define USART_CR1_PS_BIT 9 -/** Parity error interrupt enable bit */ -#define USART_CR1_PEIE_BIT 8 -/** Transmit data regsiter not empty interrupt enable bit */ -#define USART_CR1_TXEIE_BIT 7 -/** Transmission complete interrupt enable bit */ -#define USART_CR1_TCIE_BIT 6 -/** RXNE interrupt enable bit */ -#define USART_CR1_RXNEIE_BIT 5 -/** IDLE interrupt enable bit */ -#define USART_CR1_IDLEIE_BIT 4 -/** Transmitter enable bit */ -#define USART_CR1_TE_BIT 3 -/** Receiver enable bit */ -#define USART_CR1_RE_BIT 2 - -/** Word length mask */ -#define USART_CR1_M BIT(USART_CR1_M_BIT) -/** Word length: 1 start bit, 8 data bits, n stop bit */ -#define USART_CR1_M_8N1 (0 << USART_CR1_M_BIT) -/** Word length: 1 start bit, 9 data bits, n stop bit */ -#define USART_CR1_M_9N1 (1 << USART_CR1_M_BIT) -/** Wakeup method mask */ -#define USART_CR1_WAKE BIT(USART_CR1_WAKE_BIT) -/** Wakeup on idle line */ -#define USART_CR1_WAKE_IDLE (0 << USART_CR1_WAKE_BIT) -/** Wakeup on address mark */ -#define USART_CR1_WAKE_ADDR (1 << USART_CR1_WAKE_BIT) -/** Parity control enable mask */ -#define USART_CR1_PCE BIT(USART_CR1_PCE_BIT) -/** Parity selection mask */ -#define USART_CR1_PS BIT(USART_CR1_PS_BIT) -/** Parity selection: even parity */ -#define USART_CR1_PS_EVEN (0 << USART_CR1_PS_BIT) -/** Parity selection: odd parity */ -#define USART_CR1_PS_ODD (1 << USART_CR1_PS_BIT) -/** Parity error interrupt enable mask */ -#define USART_CR1_PEIE BIT(USART_CR1_PEIE_BIT) -/** Transmit data register empty interrupt enable mask */ -#define USART_CR1_TXEIE BIT(USART_CR1_TXEIE_BIT) -/** Transmission complete interrupt enable mask */ -#define USART_CR1_TCIE BIT(USART_CR1_TCIE_BIT) -/** RXNE interrupt enable mask */ -#define USART_CR1_RXNEIE BIT(USART_CR1_RXNEIE_BIT) -/** IDLE line interrupt enable mask */ -#define USART_CR1_IDLEIE BIT(USART_CR1_IDLEIE_BIT) -/** Transmitter enable mask */ -#define USART_CR1_TE BIT(USART_CR1_TE_BIT) -/** Receiver enable mask */ -#define USART_CR1_RE BIT(USART_CR1_RE_BIT) - -/* Control register 2 */ - -/** LIN mode enable bit */ -#define USART_CR2_LINEN_BIT 14 -/** Clock enable bit */ -#define USART_CR2_CLKEN_BIT 11 -/** Clock polarity bit */ -#define USART_CR2_CPOL_BIT 10 -/** Clock phase bit */ -#define USART_CR2_CPHA_BIT 9 -/** Last bit clock pulse bit */ -#define USART_CR2_LBCL_BIT 8 -/** LIN break detection interrupt enable bit */ -#define USART_CR2_LBDIE_BIT 6 -/** LIN break detection length bit */ -#define USART_CR2_LBDL_BIT 5 - -/** LIN mode enable mask */ -#define USART_CR2_LINEN BIT(USART_CR2_LINEN_BIT) -/** STOP bits mask */ -#define USART_CR2_STOP (0x3 << 12) -/** STOP bits: 1 stop bit */ -#define USART_CR2_STOP_BITS_1 (0x0 << 12) -/** - * @brief STOP bits: 0.5 stop bits - * Not available on UART4, UART5. */ -#define USART_CR2_STOP_BITS_POINT_5 (0x1 << 12) -/** STOP bits: 2 stop bits */ -#define USART_CR2_STOP_BITS_2 (0x2 << 12) -/** - * @brief STOP bits: 1.5 stop bits - * Not available on UART4, UART5. */ -#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12) -/** - * @brief Clock enable. - * Not available on UART4, UART5 */ -#define USART_CR2_CLKEN BIT(USART_CR2_CLKEN_BIT) -/** - * @brief Clock polarity mask. - * Not available on UART4, UART5 */ -#define USART_CR2_CPOL BIT(USART_CR2_CPOL_BIT) -/** Clock polarity: low */ -#define USART_CR2_CPOL_LOW (0x0 << USART_CR2_CLKEN_BIT) -/** Clock polarity: high */ -#define USART_CR2_CPOL_HIGH (0x1 << USART_CR2_CLKEN_BIT) -/** - * @brief Clock phase mask. - * Not available on UART4, UART5 */ -#define USART_CR2_CPHA BIT(USART_CR2_CPHA_BIT) -/** - * @brief Clock phase: first - * First clock transition is the first data capture edge. */ -#define USART_CR2_CPHA_FIRST (0x0 << USART_CR2_CPHA_BIT) -/** - * @brief Clock phase: second - * Second clock transition is the first data capture edge. */ -#define USART_CR2_CPHA_SECOND (0x1 << USART_CR2_CPHA_BIT) -/** - * @brief Last bit clock pulse mask. - * - * When set, the last bit transmitted causes a clock pulse in - * synchronous mode. - * - * Not available on UART4, UART5 */ -#define USART_CR2_LBCL BIT(USART_CR2_LBCL_BIT) -/** LIN break detection interrupt enable mask. */ -#define USART_CR2_LBDIE BIT(USART_CR2_LBDIE_BIT) -/** LIN break detection length. */ -#define USART_CR2_LBDL BIT(USART_CR2_LBDL_BIT) -/** LIN break detection length: 10 bits */ -#define USART_CR2_LBDL_10_BIT (0 << USART_CR2_LBDL_BIT) -/** LIN break detection length: 11 bits */ -#define USART_CR2_LBDL_11_BIT (1 << USART_CR2_LBDL_BIT) - -/* Control register 3 */ - -/** Clear to send interrupt enable bit */ -#define USART_CR3_CTSIE_BIT 10 -/** Clear to send enable bit */ -#define USART_CR3_CTSE_BIT 9 -/** Ready to send enable bit */ -#define USART_CR3_RTSE_BIT 8 -/** DMA enable transmitter bit */ -#define USART_CR3_DMAT_BIT 7 -/** DMA enable receiver bit */ -#define USART_CR3_DMAR_BIT 6 -/** Smartcard mode enable bit */ -#define USART_CR3_SCEN_BIT 5 -/** Smartcard NACK enable bit */ -#define USART_CR3_NACK_BIT 4 -/** Half-duplex selection bit */ -#define USART_CR3_HDSEL_BIT 3 -/** IrDA low power bit */ -#define USART_CR3_IRLP_BIT 2 -/** IrDA mode enable bit */ -#define USART_CR3_IREN_BIT 1 -/** Error interrupt enable bit */ -#define USART_CR3_EIE_BIT 0 - -/** - * @brief Clear to send interrupt enable - * Not available on UART4, UART5. */ -#define USART_CR3_CTSIE BIT(USART_CR3_CTSIE_BIT) -/** - * @brief Clear to send enable - * Not available on UART4, UART5. */ -#define USART_CR3_CTSE BIT(USART_CR3_CTSE_BIT) -/** - * @brief Ready to send enable - * Not available on UART4, UART5. */ -#define USART_CR3_RTSE BIT(USART_CR3_RTSE_BIT) -/** - * @brief DMA enable transmitter - * Not available on UART5. */ -#define USART_CR3_DMAT BIT(USART_CR3_DMAT_BIT) -/** - * @brief DMA enable receiver - * Not available on UART5. */ -#define USART_CR3_DMAR BIT(USART_CR3_DMAR_BIT) -/** - * @brief Smartcard mode enable - * Not available on UART4, UART5. */ -#define USART_CR3_SCEN BIT(USART_CR3_SCEN_BIT) -/** - * @brief Smartcard NACK enable - * Not available on UART4, UART5. */ -#define USART_CR3_NACK BIT(USART_CR3_NACK_BIT) -/** - * @brief Half-duplex selection - * When set, single-wire half duplex mode is selected. - */ -#define USART_CR3_HDSEL BIT(USART_CR3_HDSEL_BIT) -/** IrDA low power mode */ -#define USART_CR3_IRLP BIT(USART_CR3_IRLP_BIT) -/** IrDA mode: normal */ -#define USART_CR3_IRLP_NORMAL (0U << USART_CR3_IRLP_BIT) -/** IrDA mode: low power */ -#define USART_CR3_IRLP_LOW_POWER (1U << USART_CR3_IRLP_BIT) -/** IrDA mode enable */ -#define USART_CR3_IREN BIT(USART_CR3_IREN_BIT) -/** Error interrupt enable */ -#define USART_CR3_EIE BIT(USART_CR3_EIE_BIT) - -/* Guard time and prescaler register */ - -/** - * @brief Guard time value mask - * Used in Smartcard mode. Not available on UART4, UART5. */ -#define USART_GTPR_GT (0xFF << 8) -/** - * @brief Prescaler value mask - * Restrictions on this value apply, depending on the USART mode. Not - * available on UART4, UART5. */ -#define USART_GTPR_PSC 0xFF - -/* - * Devices - */ - -#ifndef USART_RX_BUF_SIZE -#define USART_RX_BUF_SIZE 64 -#endif - -/** USART device type */ -typedef struct usart_dev { - usart_reg_map *regs; /**< Register map */ - ring_buffer *rb; /**< RX ring buffer */ - uint32 max_baud; /**< @brief Deprecated. - * Maximum baud rate. */ - uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated. - * Actual RX buffer used by rb. - * This field will be removed in - * a future release. */ - rcc_clk_id clk_id; /**< RCC clock information */ - nvic_irq_num irq_num; /**< USART NVIC interrupt */ -} usart_dev; - -void usart_init(usart_dev *dev); - -struct gpio_dev; /* forward declaration */ -/* FIXME [PRE 0.0.13] decide if flags are necessary */ -/** - * @brief Configure GPIOs for use as USART TX/RX. - * @param udev USART device to use - * @param rx_dev RX pin gpio_dev - * @param rx RX pin bit on rx_dev - * @param tx_dev TX pin gpio_dev - * @param tx TX pin bit on tx_dev - * @param flags Currently ignored - */ -extern void usart_config_gpios_async(usart_dev *udev, - struct gpio_dev *rx_dev, uint8 rx, - struct gpio_dev *tx_dev, uint8 tx, - unsigned flags); - -#define USART_USE_PCLK 0 -void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud); - -void usart_enable(usart_dev *dev); -void usart_disable(usart_dev *dev); -void usart_foreach(void (*fn)(usart_dev *dev)); -/** - * @brief Nonblocking USART transmit - * @param dev Serial port to transmit over - * @param buf Buffer to transmit - * @param len Maximum number of bytes to transmit - * @return Number of bytes transmitted - */ -uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len); -uint32 usart_rx(usart_dev *dev, uint8 *buf, uint32 len); -void usart_putudec(usart_dev *dev, uint32 val); - -/** - * @brief Disable all serial ports. - */ -static inline void usart_disable_all(void) { - usart_foreach(usart_disable); -} - -/** - * @brief Transmit one character on a serial port. - * - * This function blocks until the character has been successfully - * transmitted. - * - * @param dev Serial port to send on. - * @param byte Byte to transmit. - */ -static inline void usart_putc(usart_dev* dev, uint8 byte) { - while (!usart_tx(dev, &byte, 1)) - ; -} - -/** - * @brief Transmit a character string on a serial port. - * - * This function blocks until str is completely transmitted. - * - * @param dev Serial port to send on - * @param str String to send - */ -static inline void usart_putstr(usart_dev *dev, const char* str) { - uint32 i = 0; - while (str[i] != '\0') { - usart_putc(dev, str[i++]); - } -} - -/** - * @brief Read one character from a serial port. - * - * It's not safe to call this function if the serial port has no data - * available. - * - * @param dev Serial port to read from - * @return byte read - * @see usart_data_available() - */ -static inline uint8 usart_getc(usart_dev *dev) { - return rb_remove(dev->rb); -} - -/** - * @brief Return the amount of data available in a serial port's RX buffer. - * @param dev Serial port to check - * @return Number of bytes in dev's RX buffer. - */ -static inline uint32 usart_data_available(usart_dev *dev) { - return rb_full_count(dev->rb); -} - -/** - * @brief Discard the contents of a serial port's RX buffer. - * @param dev Serial port whose buffer to empty. - */ -static inline void usart_reset_rx(usart_dev *dev) { - rb_reset(dev->rb); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/usb.h b/STM32F3/cores/maple/libmaple/include/libmaple/usb.h deleted file mode 100644 index ea24030..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/usb.h +++ /dev/null @@ -1,176 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010, 2011, 2012 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/* - * NOTE: This API is _unstable_ and will change drastically over time. - */ - -#ifndef _LIBMAPLE_USB_H_ -#define _LIBMAPLE_USB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/* - * Descriptors and other paraphernalia - */ - -/* Descriptor types */ - -#define USB_DESCRIPTOR_TYPE_DEVICE 0x01 -#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02 -#define USB_DESCRIPTOR_TYPE_STRING 0x03 -#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04 -#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05 - -/* Descriptor structs and declaration helpers */ - -#define USB_DESCRIPTOR_STRING_LEN(x) (2 + (x << 1)) - -#define USB_DESCRIPTOR_STRING(len) \ - struct { \ - uint8 bLength; \ - uint8 bDescriptorType; \ - uint16 bString[len]; \ - } __packed - -typedef struct usb_descriptor_device { - uint8 bLength; - uint8 bDescriptorType; - uint16 bcdUSB; - uint8 bDeviceClass; - uint8 bDeviceSubClass; - uint8 bDeviceProtocol; - uint8 bMaxPacketSize0; - uint16 idVendor; - uint16 idProduct; - uint16 bcdDevice; - uint8 iManufacturer; - uint8 iProduct; - uint8 iSerialNumber; - uint8 bNumConfigurations; -} __packed usb_descriptor_device; - -typedef struct usb_descriptor_config_header { - uint8 bLength; - uint8 bDescriptorType; - uint16 wTotalLength; - uint8 bNumInterfaces; - uint8 bConfigurationValue; - uint8 iConfiguration; - uint8 bmAttributes; - uint8 bMaxPower; -} __packed usb_descriptor_config_header; - -typedef struct usb_descriptor_interface { - uint8 bLength; - uint8 bDescriptorType; - uint8 bInterfaceNumber; - uint8 bAlternateSetting; - uint8 bNumEndpoints; - uint8 bInterfaceClass; - uint8 bInterfaceSubClass; - uint8 bInterfaceProtocol; - uint8 iInterface; -} __packed usb_descriptor_interface; - -typedef struct usb_descriptor_endpoint { - uint8 bLength; - uint8 bDescriptorType; - uint8 bEndpointAddress; - uint8 bmAttributes; - uint16 wMaxPacketSize; - uint8 bInterval; -} __packed usb_descriptor_endpoint; - -typedef struct usb_descriptor_string { - uint8 bLength; - uint8 bDescriptorType; - uint8 bString[]; -} usb_descriptor_string; - -/* Common values that go inside descriptors */ - -#define USB_CONFIG_ATTR_BUSPOWERED 0b10000000 -#define USB_CONFIG_ATTR_SELF_POWERED 0b11000000 - -#define USB_EP_TYPE_INTERRUPT 0x03 -#define USB_EP_TYPE_BULK 0x02 - -#define USB_DESCRIPTOR_ENDPOINT_IN 0x80 -#define USB_DESCRIPTOR_ENDPOINT_OUT 0x00 - -/* - * USB module core - */ - -#ifndef USB_ISR_MSK -/* Handle CTRM, WKUPM, SUSPM, ERRM, SOFM, ESOFM, RESETM */ -#define USB_ISR_MSK 0xBF00 -#endif - -typedef enum usb_dev_state { - USB_UNCONNECTED, - USB_ATTACHED, - USB_POWERED, - USB_SUSPENDED, - USB_ADDRESSED, - USB_CONFIGURED -} usb_dev_state; - -/* Encapsulates global state formerly handled by usb_lib/ */ -typedef struct usblib_dev { - uint32 irq_mask; - void (**ep_int_in)(void); - void (**ep_int_out)(void); - usb_dev_state state; - usb_dev_state prevState; - rcc_clk_id clk_id; -} usblib_dev; - -extern usblib_dev *USBLIB; - -void usb_init_usblib(usblib_dev *dev, - void (**ep_int_in)(void), - void (**ep_int_out)(void)); - -static inline uint8 usb_is_connected(usblib_dev *dev) { - return dev->state != USB_UNCONNECTED; -} - -static inline uint8 usb_is_configured(usblib_dev *dev) { - return dev->state == USB_CONFIGURED; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/usb_cdcacm.h b/STM32F3/cores/maple/libmaple/include/libmaple/usb_cdcacm.h deleted file mode 100644 index 5fe832c..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/usb_cdcacm.h +++ /dev/null @@ -1,179 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/usb_cdcacm.h - * @brief USB CDC ACM (virtual serial terminal) support - * - * IMPORTANT: this API is unstable, and may change without notice. - */ - -#ifndef _LIBMAPLE_USB_CDCACM_H_ -#define _LIBMAPLE_USB_CDCACM_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * CDC ACM Requests - */ - -#define USB_CDCACM_SET_LINE_CODING 0x20 -#define USB_CDCACM_GET_LINE_CODING 0x21 -#define USB_CDCACM_SET_COMM_FEATURE 0x02 -#define USB_CDCACM_SET_CONTROL_LINE_STATE 0x22 -#define USB_CDCACM_CONTROL_LINE_DTR (0x01) -#define USB_CDCACM_CONTROL_LINE_RTS (0x02) - -/* - * Descriptors, etc. - */ - -#define CDC_FUNCTIONAL_DESCRIPTOR_SIZE(DataSize) (3 + DataSize) -#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \ - struct { \ - uint8 bLength; \ - uint8 bDescriptorType; \ - uint8 SubType; \ - uint8 Data[DataSize]; \ - } __packed - -#define USB_DEVICE_CLASS_CDC 0x02 -#define USB_DEVICE_SUBCLASS_CDC 0x00 -#define USB_INTERFACE_CLASS_CDC 0x02 -#define USB_INTERFACE_SUBCLASS_CDC_ACM 0x02 -#define USB_INTERFACE_CLASS_DIC 0x0A - -/* - * Endpoint configuration - */ - -#define USB_CDCACM_CTRL_ENDP 0 -#define USB_CDCACM_CTRL_RX_ADDR 0x40 -#define USB_CDCACM_CTRL_TX_ADDR 0x80 -#define USB_CDCACM_CTRL_EPSIZE 0x40 - -#define USB_CDCACM_TX_ENDP 1 -#define USB_CDCACM_TX_ADDR 0xC0 -#define USB_CDCACM_TX_EPSIZE 0x40 - -#define USB_CDCACM_MANAGEMENT_ENDP 2 -#define USB_CDCACM_MANAGEMENT_ADDR 0x100 -#define USB_CDCACM_MANAGEMENT_EPSIZE 0x40 - -#define USB_CDCACM_RX_ENDP 3 -#define USB_CDCACM_RX_ADDR 0x110 -#define USB_CDCACM_RX_EPSIZE 0x40 - -#ifndef __cplusplus -#define USB_CDCACM_DECLARE_DEV_DESC(vid, pid) \ - { \ - .bLength = sizeof(usb_descriptor_device), \ - .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, \ - .bcdUSB = 0x0200, \ - .bDeviceClass = USB_DEVICE_CLASS_CDC, \ - .bDeviceSubClass = USB_DEVICE_SUBCLASS_CDC, \ - .bDeviceProtocol = 0x00, \ - .bMaxPacketSize0 = 0x40, \ - .idVendor = vid, \ - .idProduct = pid, \ - .bcdDevice = 0x0200, \ - .iManufacturer = 0x01, \ - .iProduct = 0x02, \ - .iSerialNumber = 0x00, \ - .bNumConfigurations = 0x01, \ - } -#endif - -/* - * CDC ACM interface - */ - -void usb_cdcacm_enable(gpio_dev*, uint8); -void usb_cdcacm_disable(gpio_dev*, uint8); - -void usb_cdcacm_putc(char ch); -uint32 usb_cdcacm_tx(const uint8* buf, uint32 len); -uint32 usb_cdcacm_rx(uint8* buf, uint32 len); -uint32 usb_cdcacm_peek(uint8* buf, uint32 len); - -uint32 usb_cdcacm_data_available(void); /* in RX buffer */ -uint16 usb_cdcacm_get_pending(void); -uint8 usb_cdcacm_is_transmitting(void); - -uint8 usb_cdcacm_get_dtr(void); -uint8 usb_cdcacm_get_rts(void); - -typedef struct usb_cdcacm_line_coding { - uint32 dwDTERate; /* Baud rate */ - -#define USB_CDCACM_STOP_BITS_1 0 -#define USB_CDCACM_STOP_BITS_1_5 1 -#define USB_CDCACM_STOP_BITS_2 2 - uint8 bCharFormat; /* Stop bits */ - -#define USB_CDCACM_PARITY_NONE 0 -#define USB_CDCACM_PARITY_ODD 1 -#define USB_CDCACM_PARITY_EVEN 2 -#define USB_CDCACM_PARITY_MARK 3 -#define USB_CDCACM_PARITY_SPACE 4 - uint8 bParityType; /* Parity type */ - - uint8 bDataBits; /* Data bits: 5, 6, 7, 8, or 16 */ -} __packed usb_cdcacm_line_coding; - -/* Retrieve a copy of the current line coding structure. */ -void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding*); - -/* Line coding conveniences. */ -int usb_cdcacm_get_baud(void); /* dwDTERate */ -int usb_cdcacm_get_stop_bits(void); /* bCharFormat */ -int usb_cdcacm_get_parity(void); /* bParityType */ -int usb_cdcacm_get_n_data_bits(void); /* bDataBits */ - -/* - * Hack: hooks for bootloader reset signalling - */ - -#define USB_CDCACM_HOOK_RX 0x1 -#define USB_CDCACM_HOOK_IFACE_SETUP 0x2 - -void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)); - -static __always_inline void usb_cdcacm_remove_hooks(unsigned hook_flags) { - usb_cdcacm_set_hooks(hook_flags, 0); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/util.h b/STM32F3/cores/maple/libmaple/include/libmaple/util.h deleted file mode 100644 index 5a70348..0000000 --- a/STM32F3/cores/maple/libmaple/include/libmaple/util.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/include/libmaple/util.h - * @brief Miscellaneous utility macros and procedures. - */ - -#ifndef _LIBMAPLE_UTIL_H_ -#define _LIBMAPLE_UTIL_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Bit manipulation - */ - -/** 1UL shifted left by 'shift' */ -#define BIT(shift) (1UL << (shift)) -/** 'Mask' shifted left by 'shift' */ -#define BIT_MASK_SHIFT(mask, shift) ((mask) << (shift)) -/** Bits m to n of x */ -#define GET_BITS(x, m, n) ((((uint32)x) << (31 - (n))) >> ((31 - (n)) + (m))) -/** True iff v is a power of two (1, 2, 4, 8, ...) */ -#define IS_POWER_OF_TWO(v) ((v) && !((v) & ((v) - 1))) - -/* - * Failure routines - */ - -void __error(void); -void _fail(const char*, int, const char*); -void throb(void); - -/* - * Asserts and debug levels - */ - -#define DEBUG_NONE 0 -#define DEBUG_FAULT 1 -#define DEBUG_ALL 2 - -/** - * \def DEBUG_LEVEL - * - * Controls the level of assertion checking. - * - * The higher the debug level, the more assertions will be compiled - * in. This increases the amount of debugging information, but slows - * down (and increases the size of) the binary. - * - * The debug levels, from lowest to highest, are DEBUG_NONE, - * DEBUG_FAULT, and DEBUG_ALL. The default level is DEBUG_ALL. - */ - -#ifndef DEBUG_LEVEL -#define DEBUG_LEVEL DEBUG_ALL -#endif - -#if DEBUG_LEVEL >= DEBUG_ALL -#define ASSERT(exp) \ - if (exp) { \ - } else { \ - _fail(__FILE__, __LINE__, #exp); \ - } -#else -#define ASSERT(exp) (void)((0)) -#endif - -#if DEBUG_LEVEL >= DEBUG_FAULT -#define ASSERT_FAULT(exp) \ - if (exp) { \ - } else { \ - _fail(__FILE__, __LINE__, #exp); \ - } -#else -#define ASSERT_FAULT(exp) (void)((0)) -#endif - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/iwdg.c b/STM32F3/cores/maple/libmaple/iwdg.c deleted file mode 100644 index 2456235..0000000 --- a/STM32F3/cores/maple/libmaple/iwdg.c +++ /dev/null @@ -1,62 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/iwdg.c - * @brief Independent watchdog (IWDG) support - */ - -#include - -/** - * @brief Initialise and start the watchdog - * - * The prescaler and reload set the timeout. For example, a prescaler - * of IWDG_PRE_32 divides the 40 kHz clock by 32 and gives roughly 1 - * ms per reload. - * - * @param prescaler Prescaler for the 40 kHz IWDG clock. - * @param reload Independent watchdog counter reload value. - */ -void iwdg_init(iwdg_prescaler prescaler, uint16 reload) { - IWDG_BASE->KR = IWDG_KR_UNLOCK; - IWDG_BASE->PR = prescaler; - IWDG_BASE->RLR = reload; - - /* Start things off */ - IWDG_BASE->KR = IWDG_KR_START; - iwdg_feed(); -} - -/** - * @brief Reset the IWDG counter. - * - * Calling this function will cause the IWDG counter to be reset to - * its reload value. - */ -void iwdg_feed(void) { - IWDG_BASE->KR = IWDG_KR_FEED; -} diff --git a/STM32F3/cores/maple/libmaple/nvic.c b/STM32F3/cores/maple/libmaple/nvic.c deleted file mode 100644 index 149e780..0000000 --- a/STM32F3/cores/maple/libmaple/nvic.c +++ /dev/null @@ -1,103 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/nvic.c - * @brief Nested vector interrupt controller support. - */ - -#include -#include -#include - -/** - * @brief Set interrupt priority for an interrupt line - * - * Note: The STM32 only implements 4 bits of priority, ignoring the - * lower 4 bits. This means there are only 16 levels of priority. - * Bits[3:0] read as zero and ignore writes. - * - * @param irqn device to set - * @param priority Priority to set, 0 being highest priority and 15 - * being lowest. - */ -void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority) { - if (irqn < 0) { - /* This interrupt is in the system handler block */ - SCB_BASE->SHP[((uint32)irqn & 0xF) - 4] = (priority & 0xF) << 4; - } else { - NVIC_BASE->IP[irqn] = (priority & 0xF) << 4; - } -} - -/** - * @brief Initialize the NVIC, setting interrupts to a default priority. - */ -void nvic_init(uint32 address, uint32 offset) { - uint32 i; - - nvic_set_vector_table(address, offset); - - /* - * Lower priority level for all peripheral interrupts to lowest - * possible. - */ - for (i = 0; i < STM32_NR_INTERRUPTS; i++) { - nvic_irq_set_priority((nvic_irq_num)i, 0xF); - } - - /* Lower systick interrupt priority to lowest level */ - nvic_irq_set_priority(NVIC_SYSTICK, 0xF); -} - -/** - * @brief Set the vector table base address. - * - * For stand-alone products, the vector table base address is normally - * the start of Flash (0x08000000). - * - * @param address Vector table base address. - * @param offset Offset from address. Some restrictions apply to the - * use of nonzero offsets; see the ARM Cortex M3 - * Technical Reference Manual. - */ -void nvic_set_vector_table(uint32 address, uint32 offset) { - SCB_BASE->VTOR = address | (offset & 0x1FFFFF80); -} - -/** - * @brief Force a system reset. - * - * Resets all major system components, excluding debug. - */ -void nvic_sys_reset() { - uint32 prigroup = SCB_BASE->AIRCR & SCB_AIRCR_PRIGROUP; - SCB_BASE->AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ | prigroup; - asm volatile("dsb"); - while (1) - ; -} diff --git a/STM32F3/cores/maple/libmaple/rcc.c b/STM32F3/cores/maple/libmaple/rcc.c deleted file mode 100644 index 8e7d1ea..0000000 --- a/STM32F3/cores/maple/libmaple/rcc.c +++ /dev/null @@ -1,169 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/rcc.c - * @brief Portable RCC routines. - */ - -#include - -#include "rcc_private.h" - -/** - * @brief Get a peripheral's clock domain - * @param id Clock ID of the peripheral whose clock domain to return - * @return Clock source for the given clock ID - */ -rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { - return rcc_dev_table[id].clk_domain; -} - -/** - * @brief Switch the clock used as the source of the system clock. - * - * After switching the source, this function blocks until the new - * clock source is in use. - * - * @param sysclk_src New system clock source. - * @see rcc_sysclk_src - */ -void rcc_switch_sysclk(rcc_sysclk_src sysclk_src) { - uint32 cfgr = RCC_BASE->CFGR; - cfgr &= ~RCC_CFGR_SW; - cfgr |= sysclk_src; - - /* Switch SYSCLK source. */ - RCC_BASE->CFGR = cfgr; - - /* Wait for new source to come into use. */ - while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != (sysclk_src << 2)) - ; -} - -/* - * Turning clocks off and on, querying their status. - */ - -/* IMPORTANT NOTE FOR IMPLEMENTORS: - * - * libmaple assumes that enum rcc_clk enumerators are two-byte - * values, stored in a uint16, in the following way: - * - * - The high-order byte is the byte offset (from RCC_BASE) of the register - * to touch when turning on or off the given clock. - * - * - The low-order byte is the bit in that register that turns the - * clock on or off. - * - * Example for STM32F1: Turning on the high-speed external clock (HSE) - * involves setting HSEON, bit 16, of RCC_CR. The high-order byte is - * then offsetof(struct rcc_reg_map, CR) = 0, and the low-order byte - * is 16. - * - * The corresponding value of RCC_CLK_HSE is thus (0 << 8) | 16 = 16. - * - * On all known STM32 series, this encoding has the property that - * adding one to the low byte also gives the bit to check to determine - * if the clock is ready. For example, on STM32F1, RCC_CR_HSERDY is - * bit 17. If that's not the case on your series, rcc_is_clk_ready() - * won't work for you. */ - -/* Returns the RCC register which controls the clock source. */ -static inline __io uint32* rcc_clk_reg(rcc_clk clock) { - return (__io uint32*)((__io uint8*)RCC_BASE + (clock >> 8)); -} - -/* Returns a mask in rcc_clk_reg(clock) to be used for turning the - * clock on and off */ -static inline uint32 rcc_clk_on_mask(rcc_clk clock) { - return 1 << (clock & 0xFF); -} - -/* Returns a mask in rcc_clk_reg(clock) to be used when checking the - * readiness of the clock. */ -static inline uint32 rcc_clk_ready_mask(rcc_clk clock) { - return rcc_clk_on_mask(clock) << 1; -} - -/** - * @brief Turn on a clock source. - * - * After this routine exits, callers should ensure that the clock - * source is ready by waiting until rcc_is_clk_ready(clock) returns - * true. - * - * @param clock Clock to turn on. - * @see rcc_turn_off_clk() - * @see rcc_is_clk_ready() - */ -void rcc_turn_on_clk(rcc_clk clock) { - *rcc_clk_reg(clock) |= rcc_clk_on_mask(clock); -} - -/** - * @brief Turn off a clock source. - * - * In certain configurations, certain clock sources cannot be safely - * turned off. (For example, the main PLL on STM32F1 devices cannot be - * turned off if it has been selected as the SYSCLK source). Consult - * the reference material for your MCU to ensure it is safe to call - * this function. - * - * @param clock Clock to turn off. - * @see rcc_turn_on_clk() - * @see rcc_is_clk_ready() - */ -void rcc_turn_off_clk(rcc_clk clock) { - *rcc_clk_reg(clock) &= ~rcc_clk_on_mask(clock); -} - -/** - * @brief Check if a clock is on. - * @param clock Clock to check. - * @return 1 if the clock is on, 0 if the clock is off. - */ -int rcc_is_clk_on(rcc_clk clock) { - return !!(*rcc_clk_reg(clock) & rcc_clk_on_mask(clock)); -} - -/** - * @brief Check if a clock source is ready. - * - * In general, it is not safe to rely on a clock source unless this - * function returns nonzero. Also note that this function may return - * nonzero for a short period of time after a clock has been turned - * off. Consult the reference material for your MCU for more details. - * - * @param clock Clock whose readiness to check for. - * @return Nonzero if the clock is ready, zero otherwise. - * @see rcc_turn_on_clk() - * @see rcc_turn_off_clk() - */ -int rcc_is_clk_ready(rcc_clk clock) { - return (int)(*rcc_clk_reg(clock) & rcc_clk_ready_mask(clock)); -} diff --git a/STM32F3/cores/maple/libmaple/rcc_private.h b/STM32F3/cores/maple/libmaple/rcc_private.h deleted file mode 100644 index 66eaf00..0000000 --- a/STM32F3/cores/maple/libmaple/rcc_private.h +++ /dev/null @@ -1,67 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/* - * RCC private header. - */ - -#ifndef _LIBMAPLE_PRIVATE_RCC_H_ -#define _LIBMAPLE_PRIVATE_RCC_H_ - -#include - -struct rcc_dev_info { - const rcc_clk_domain clk_domain; - const uint8 line_num; -}; - -extern const struct rcc_dev_info rcc_dev_table[]; - -static inline void rcc_do_clk_enable(__io uint32** enable_regs, - rcc_clk_id id) { - __io uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; - uint8 line_num = rcc_dev_table[id].line_num; - bb_peri_set_bit(enable_reg, line_num, 1); -} - -static inline void rcc_do_reset_dev(__io uint32** reset_regs, - rcc_clk_id id) { - __io uint32 *reset_reg = reset_regs[rcc_dev_clk(id)]; - uint8 line_num = rcc_dev_table[id].line_num; - bb_peri_set_bit(reset_reg, line_num, 1); - bb_peri_set_bit(reset_reg, line_num, 0); -} - -static inline void rcc_do_set_prescaler(const uint32 *masks, - rcc_prescaler prescaler, - uint32 divider) { - uint32 cfgr = RCC_BASE->CFGR; - cfgr &= ~masks[prescaler]; - cfgr |= divider; - RCC_BASE->CFGR = cfgr; -} - -#endif diff --git a/STM32F3/cores/maple/libmaple/rules.mk b/STM32F3/cores/maple/libmaple/rules.mk deleted file mode 100644 index 0b541ed..0000000 --- a/STM32F3/cores/maple/libmaple/rules.mk +++ /dev/null @@ -1,53 +0,0 @@ -# Standard things -sp := $(sp).x -dirstack_$(sp) := $(d) -d := $(dir) -BUILDDIRS += $(BUILD_PATH)/$(d) - -LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -I$(LIBMAPLE_MODULE_SERIES)/include -LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) - -# Local flags -CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror - -# Local rules and targets -cSRCS_$(d) := adc.c -cSRCS_$(d) += dac.c -cSRCS_$(d) += dma.c -cSRCS_$(d) += exti.c -cSRCS_$(d) += flash.c -cSRCS_$(d) += gpio.c -cSRCS_$(d) += iwdg.c -cSRCS_$(d) += nvic.c -cSRCS_$(d) += pwr.c -cSRCS_$(d) += rcc.c -cSRCS_$(d) += spi.c -cSRCS_$(d) += systick.c -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),stm32f2 stm32f3)) # SYSCFG peripheral available only on F2, F3 -cSRCS_$(d) += syscfg.c -endif -cSRCS_$(d) += timer.c -cSRCS_$(d) += usart.c -cSRCS_$(d) += usart_private.c -cSRCS_$(d) += util.c -sSRCS_$(d) := exc.S -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),stm32f1 stm32f3)) # TODO port I2C to F2 -cSRCS_$(d) += i2c.c -cSRCS_$(d) += bkp.c -endif - -cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) - -OBJS_$(d) := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) -DEPS_$(d) := $(OBJS_$(d):%.o=%.d) - -$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) -$(OBJS_$(d)): TGT_ASFLAGS := - -TGT_BIN += $(OBJS_$(d)) - -# Standard things --include $(DEPS_$(d)) -d := $(dirstack_$(sp)) -sp := $(basename $(sp)) diff --git a/STM32F3/cores/maple/libmaple/spi.c b/STM32F3/cores/maple/libmaple/spi.c deleted file mode 100644 index ec008d4..0000000 --- a/STM32F3/cores/maple/libmaple/spi.c +++ /dev/null @@ -1,129 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/spi.c - * @author Marti Bolivar - * @brief Serial Peripheral Interface (SPI) support. - * Currently, there is no Integrated Interchip Sound (I2S) support. - */ - -#include -#include - -/* - * SPI convenience routines - */ - -/** - * @brief Initialize and reset a SPI device. - * @param dev Device to initialize and reset. - */ -void spi_init(spi_dev *dev) { - rcc_clk_enable(dev->clk_id); - rcc_reset_dev(dev->clk_id); -} - -/** - * @brief Configure and enable a SPI device as bus master. - * - * The device's peripheral will be disabled before being reconfigured. - * - * @param dev Device to configure as bus master - * @param baud Bus baud rate - * @param mode SPI mode - * @param flags Logical OR of spi_cfg_flag values. - * @see spi_cfg_flag - */ -void spi_master_enable(spi_dev *dev, - spi_baud_rate baud, - spi_mode mode, - uint32 flags) { - spi_reconfigure(dev, baud | flags | SPI_CR1_MSTR | mode); -} - -/** - * @brief Configure and enable a SPI device as a bus slave. - * - * The device's peripheral will be disabled before being reconfigured. - * - * @param dev Device to configure as a bus slave - * @param mode SPI mode - * @param flags Logical OR of spi_cfg_flag values. - * @see spi_cfg_flag - */ -void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) { - spi_reconfigure(dev, flags | mode); -} - -/** - * @brief Enable a SPI peripheral - * @param dev Device to enable - */ -void spi_peripheral_enable(spi_dev *dev) { - bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 1); -} - -/** - * @brief Disable a SPI peripheral - * @param dev Device to disable - */ -void spi_peripheral_disable(spi_dev *dev) { - bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 0); -} - -/** - * @brief Enable DMA requests whenever the transmit buffer is empty - * @param dev SPI device on which to enable TX DMA requests - */ -void spi_tx_dma_enable(spi_dev *dev) { - bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 1); -} - -/** - * @brief Disable DMA requests whenever the transmit buffer is empty - * @param dev SPI device on which to disable TX DMA requests - */ -void spi_tx_dma_disable(spi_dev *dev) { - bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 0); -} - -/** - * @brief Enable DMA requests whenever the receive buffer is empty - * @param dev SPI device on which to enable RX DMA requests - */ -void spi_rx_dma_enable(spi_dev *dev) { - bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 1); -} - -/** - * @brief Disable DMA requests whenever the receive buffer is empty - * @param dev SPI device on which to disable RX DMA requests - */ -void spi_rx_dma_disable(spi_dev *dev) { - bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 0); -} diff --git a/STM32F3/cores/maple/libmaple/spi_private.h b/STM32F3/cores/maple/libmaple/spi_private.h deleted file mode 100644 index f0e0bd1..0000000 --- a/STM32F3/cores/maple/libmaple/spi_private.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifndef _LIBMAPLE_SPI_PRIVATE_H_ -#define _LIBMAPLE_SPI_PRIVATE_H_ - -#define SPI_DEV(num) \ - { \ - .regs = SPI##num##_BASE, \ - .clk_id = RCC_SPI##num, \ - .irq_num = NVIC_SPI##num, \ - } - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32_private.h b/STM32F3/cores/maple/libmaple/stm32_private.h deleted file mode 100644 index 427417a..0000000 --- a/STM32F3/cores/maple/libmaple/stm32_private.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -#ifndef _LIBMAPLE_STM32_PRIVATE_H_ -#define _LIBMAPLE_STM32_PRIVATE_H_ - -typedef enum stm32_mem_block_purpose { - STM32_BLOCK_CODE, - STM32_BLOCK_SRAM, - STM32_BLOCK_PERIPH, - STM32_BLOCK_FSMC_1_2, - STM32_BLOCK_FSMC_3_4, - STM32_BLOCK_FSMC_REG, - STM32_BLOCK_UNUSED, - STM32_BLOCK_CORTEX_INTERNAL, -} stm32_mem_block_purpose; - -static inline stm32_mem_block_purpose stm32_block_purpose(void *addr) { - return (stm32_mem_block_purpose)((unsigned)addr >> 29); -} - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_adc.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_adc.c deleted file mode 100644 index 982d6ea..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_adc.c +++ /dev/null @@ -1,412 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/adc.c - * @author Marti Bolivar , - * Perry Hung , - * F3-port by Hanspeter Portner - * @brief STM32F3 ADC support. - */ - -#include -#include -#include - -/* - * Devices - */ - -static adc_private_data adc1_priv; -static adc_dev adc1 = { - .regs = ADC1_BASE, - .clk_id = RCC_ADC12, - .priv = &adc1_priv -}; -/** ADC1 device. */ -const adc_dev *ADC1 = &adc1; - -static adc_private_data adc2_priv; -static adc_dev adc2 = { - .regs = ADC2_BASE, - .clk_id = RCC_ADC12, - .priv = &adc2_priv -}; -/** ADC2 device. */ -const adc_dev *ADC2 = &adc2; - -#if STM32_F3_LINE == STM32_F3_LINE_303 -static adc_private_data adc3_priv; -static adc_dev adc3 = { - .regs = ADC3_BASE, - .clk_id = RCC_ADC34, - .priv = &adc3_priv -}; -/** ADC3 device. */ -const adc_dev *ADC3 = &adc3; - -static adc_private_data adc4_priv; -static adc_dev adc4 = { - .regs = ADC4_BASE, - .clk_id = RCC_ADC34, - .priv = &adc4_priv -}; -/** ADC4 device. */ -const adc_dev *ADC4 = &adc4; -#endif - -/* - * STM32F3 routines - */ - -static inline void adc_check_regular_notongoing(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - if(regs->CR & ADC_CR_ADSTART) /* check for ongoing regular channel conversion */ - { - regs->CR |= ADC_CR_ADSTP; /* stop regular channel conversion */ - while(regs->CR & ADC_CR_ADSTP) - ; /* wait for conversion to stop */ - } -} - -static inline void adc_check_injected_notongoing(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - if(regs->CR & ADC_CR_JADSTART) /* check for ongoing injected channel conversion */ - { - regs->CR |= ADC_CR_JADSTP; /* stop injected channel conversion */ - while(regs->CR & ADC_CR_JADSTP) - ; /* wait for conversion to stop */ - } -} - -void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) { - adc_check_regular_notongoing(dev); - - uint32 cfgr = dev->regs->CFGR; - cfgr &= ~ADC_CFGR_EXTSEL; - cfgr |= event; - dev->regs->CFGR = cfgr; -} - -void adc_set_resolution(const adc_dev *dev, adc_resolution res) { - adc_check_regular_notongoing(dev); - adc_check_injected_notongoing(dev); - - uint32 cfgr = dev->regs->CFGR; - cfgr &= ~ADC_CFGR_RES; - cfgr |= res; - dev->regs->CFGR = cfgr; -} - -void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) { - adc_check_regular_notongoing(dev); - adc_check_injected_notongoing(dev); - - uint32 adc_smpr1_val = 0, adc_smpr2_val = 0; - int i; - - for(i = 0; i < 9; i++) { - /* ADC_SMPR1 determines sample time for channels [1,9] */ - adc_smpr1_val |= smp_rate << (i * 3 + 3); - /* ADC_SMPR2 determines sample time for channels [10,18] */ - adc_smpr2_val |= smp_rate << (i * 3); - } - - dev->regs->SMPR1 = adc_smpr1_val; - dev->regs->SMPR2 = adc_smpr2_val; -} - -void adc_enable_scan(const adc_dev *dev) { - /* FIXME nonexistent in F3 series */ -} - -void adc_disable_scan(const adc_dev *dev) { - /* FIXME nonexistent in F3 series*/ -} - -void adc_enable_continuous(const adc_dev *dev) { - bb_peri_set_bit(&dev->regs->CFGR, ADC_CFGR_CONT_BIT, 1); -} - -void adc_disable_continuous(const adc_dev *dev) { - bb_peri_set_bit(&dev->regs->CFGR, ADC_CFGR_CONT_BIT, 0); -} - -#define BITS_PER_SQ 6 -#define SQs_PER_SQR 5 -void adc_set_conv_seq(const adc_dev *dev, const uint8 *channels, uint8 len) { - ASSERT( (0 < len) && (len <= 16) ); - uint8 i; - uint32 val = 0; - uint8 lshift; - __io uint32 *sqr = &dev->regs->SQR1; - - for (i=0; iregs; - - adc_set_conv_seq(dev, &channel, 1); - - regs->CR |= ADC_CR_ADSTART; /* start conversion */ - while (!(regs->ISR & ADC_ISR_EOC)) - ; /* wait until done */ - - return (uint16)(regs->DR & ADC_DR_RDATA); -} - -void adc_attach_interrupt(const adc_dev *dev, uint32 interrupt_flags, - void (*handler)(adc_callback_data*), void *arg) { - adc_private_data *priv = dev->priv; - priv->handler = handler; - priv->handler_flags = interrupt_flags; - priv->cb_data.arg = arg; - adc_enable_interrupts(dev, interrupt_flags); -} - -void adc_detach_interrupt(const adc_dev *dev) { - adc_private_data *priv; - adc_disable_interrupts(dev, ADC_ALL_INTERRUPTS); - priv = dev->priv; - priv->handler = NULL; - priv->handler_flags = 0; -} - -void adc_enable_interrupts(const adc_dev *dev, uint32 interrupt_flags) { - uint32 ier = dev->regs->IER; - ier |= interrupt_flags; - dev->regs->IER = ier; - _adc_enable_dev_irq(dev); -} - -void adc_disable_interrupts(const adc_dev *dev, uint32 interrupt_flags) { - /* Don't use nvic_irq_disable()! IRQs are shared among ADCs. */ - uint32 ier = dev->regs->IER; - ier &= ~interrupt_flags; - dev->regs->IER = ier; -} - -void adc_calibrate(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - - if( (regs->CR & ADC_CR_ADVREGEN) != ADC_CR_ADVREGEN_ENABLE) - adc_regulator_enable(dev); /* ensure that voltage regulator is enabled */ - - if(regs->CR & ADC_CR_ADEN) - adc_disable(dev); /* ensure that ADC is disabled */ - - regs->CR &= ~ADC_CR_ADCALDIF; /* calibrate in single-ended mode */ - regs->CR |= ADC_CR_ADCAL; /* start calibration */ - while (regs->CR & ADC_CR_ADCAL) - ; /* wait until done */ - - regs->CR |= ADC_CR_ADCALDIF; /* calibrate in differential mode */ - regs->CR |= ADC_CR_ADCAL; /* start calibration */ - while (regs->CR & ADC_CR_ADCAL) - ; /* wait until done */ -} - -void adc_set_exttrig(const adc_dev *dev, adc_exttrig_mode mode) { - adc_reg_map *regs = dev->regs; - regs->CFGR &= ~ADC_CFGR_EXTEN; - regs->CFGR |= mode; -} - -void adc_set_prescaler(adc_prescaler pre) { - if (pre & 0x10) { /* PLL is used as clock source */ - ADC12_BASE->CCR &= ~ADC_CCR_CKMODE; -#if STM32_F3_LINE == STM32_F3_LINE_303 - ADC34_BASE->CCR &= ~ADC_CCR_CKMODE; -#endif - - uint32 cfgr2 = RCC_BASE->CFGR2; - - cfgr2 &= ~RCC_CFGR2_ADC12PRES; // clear register - cfgr2 |= (uint32)pre << RCC_CFGR2_ADC12PRES_SHIFT; // set register - -#if STM32_F3_LINE == STM32_F3_LINE_303 - cfgr2 &= ~RCC_CFGR2_ADC34PRES; // clear register - cfgr2 |= (uint32)pre << RCC_CFGR2_ADC34PRES_SHIFT; // set register -#endif - - RCC_BASE->CFGR2 = cfgr2; - } else { /* AHB bus is used as clock source */ - /* FIXME does not work with current wirish booting routine */ - uint32 tmp; - - tmp = ADC12_BASE->CCR; - tmp &= ~ADC_CCR_CKMODE; - tmp |= pre << ADC_CCR_CKMODE_SHIFT; - ADC12_BASE->CCR = tmp; - -#if STM32_F3_LINE == STM32_F3_LINE_303 - tmp = ADC34_BASE->CCR; - tmp &= ~ADC_CCR_CKMODE; - tmp |= pre << ADC_CCR_CKMODE_SHIFT; - ADC34_BASE->CCR = tmp; -#endif - } -} - -void adc_foreach(void (*fn)(const adc_dev*)) { - fn(ADC1); - fn(ADC2); -#if STM32_F3_LINE == STM32_F3_LINE_303 - fn(ADC3); - fn(ADC4); -#endif -} - -void adc_config_gpio(const adc_dev *ignored, gpio_dev *gdev, uint8 bit) { - gpio_set_modef(gdev, bit, GPIO_MODE_ANALOG, GPIO_MODEF_PUPD_NONE); -} - -void adc_enable_single_swstart(const adc_dev *dev) { - int check_dev_adc = dev == ADC1; -#if STM32_F3_LINE == STM32_F3_LINE_303 - check_dev_adc = (check_dev_adc || dev == ADC3); -#endif - if (check_dev_adc) - adc_init(dev); /* FIXME hack needed for wirish, as master and slave ADC share the same reset register */ - adc_set_exttrig(dev, ADC_EXTTRIG_MODE_SOFTWARE); - adc_regulator_enable(dev); - adc_calibrate(dev); - adc_enable(dev); -} - -void adc_set_reg_seqlen(const adc_dev *dev, uint8 length) { - adc_check_regular_notongoing(dev); - - uint32 tmp = dev->regs->SQR1; - tmp &= ~ADC_SQR1_L; - tmp |= (length - 1) & ADC_SQR1_L; - dev->regs->SQR1 = tmp; -} - -void adc_enable(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - - while( (regs->CR & ADC_CR_ADVREGEN) != ADC_CR_ADVREGEN_ENABLE) - adc_regulator_enable(dev); /* ensure that voltage regulator is enabled */ - - regs->CR |= ADC_CR_ADEN; /* enable ADC */ - while (!(regs->ISR & ADC_ISR_ADRDY)) - ; /* wait until ADC is ready */ -} - -void adc_disable(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - - adc_check_regular_notongoing(dev); - adc_check_injected_notongoing(dev); - - regs->CR |= ADC_CR_ADDIS; /* disable ADC */ - while(regs->CR & ADC_CR_ADEN) - ; /* wait until ADC is effectively disabled */ -} - -void adc_regulator_enable(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - - regs->CR &= ~ADC_CR_ADVREGEN; - regs->CR |= ADC_CR_ADVREGEN_ENABLE; - - delay_us(10); /* 10us are worst case */ -} - -void adc_regulator_disable(const adc_dev *dev) { - adc_reg_map *regs = dev->regs; - - regs->CR &= ~ADC_CR_ADVREGEN; - regs->CR |= ADC_CR_ADVREGEN_DISABLE; -} - -/* - * Private API - */ - -void _adc_enable_dev_irq(const adc_dev *dev) { - if ( (dev == ADC1) || (dev == ADC2) ) - nvic_irq_enable(NVIC_ADC1_2); -#if STM32_F3_LINE == STM32_F3_LINE_303 - else { - if (dev == ADC3) - nvic_irq_enable(NVIC_ADC3); - else // dev == ADC4 - nvic_irq_enable(NVIC_ADC4); - } -#endif -} - -/* IRQ handler for adc_attach_interrupt() */ -static __always_inline void adc_irq(const adc_dev *dev) { - adc_private_data *priv = dev->priv; - uint32 irq_flags = dev->regs->ISR & priv->handler_flags; - - if (!irq_flags) { - /* The user isn't interested in this IRQ. */ - return; - } else if (priv->handler) { - priv->cb_data.irq_flags = irq_flags; - priv->handler(&priv->cb_data); - } -} - -/* - * IRQ handlers for adc_attach_interrupt() - */ -/* -void __irq_adc1_2(void) { - adc_irq(ADC1); - adc_irq(ADC2); -} - -#if STM32_F3_LINE == STM32_F3_LINE_303 -void __irq_adc3(void) { - adc_irq(ADC3); -} - -void __irq_adc4(void) { - adc_irq(ADC4); -} -#endif -*/ diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_bkp.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_bkp.c deleted file mode 100644 index f6ac4d1..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_bkp.c +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/bkp.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 backup register support. - */ - -#include -#include -#include - -void bkp_init(void) { - /* Don't call pwr_init(), or you'll reset the device. We just - * need the clock. */ - rcc_clk_enable(RCC_PWR); -} - -inline __io uint32* bkp_data_register(uint8 reg) { - if (reg < 1 || reg > BKP_NR_DATA_REGS) - return NULL; - else - return (uint32*)BKP_BASE + (reg-1); // regs are accessed from 1-16 -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_comp.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_comp.c deleted file mode 100644 index 527be71..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_comp.c +++ /dev/null @@ -1,61 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/comp.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Comparator support. - */ - -#include - -/* - * Devices - */ - -static comp_dev comp1 = { .regs = COMP1_BASE }; const comp_dev *COMP1 = &comp1; -static comp_dev comp2 = { .regs = COMP2_BASE }; const comp_dev *COMP2 = &comp2; -static comp_dev comp3 = { .regs = COMP3_BASE }; const comp_dev *COMP3 = &comp3; -static comp_dev comp4 = { .regs = COMP4_BASE }; const comp_dev *COMP4 = &comp4; -static comp_dev comp5 = { .regs = COMP5_BASE }; const comp_dev *COMP5 = &comp5; -static comp_dev comp6 = { .regs = COMP6_BASE }; const comp_dev *COMP6 = &comp6; -static comp_dev comp7 = { .regs = COMP7_BASE }; const comp_dev *COMP7 = &comp7; - -void __irq_comp123(void) { - //TODO -} - -void __irq_com456(void) { - //TODO -} - -void __irq_comp7(void) { - //TODO -} - -/* TODO - * actually implement me ;-) - */ diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_dma.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_dma.c deleted file mode 100644 index 317c283..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_dma.c +++ /dev/null @@ -1,364 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/dma.c - * @author Marti Bolivar , - * Original implementation by Michael Hope, - * F3-port by Hanspeter Portner - * @brief STM32F3 DMA support. - */ - -#include -#include - -/* Hack to ensure inlining in dma_irq_handler() */ -#define DMA_GET_HANDLER(dev, tube) (dev->handlers[tube - 1].handler) -#include "dma_private.h" - -/* - * Devices - */ - -static dma_dev dma1 = { - .regs = DMA1_BASE, - .clk_id = RCC_DMA1, - .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH2 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH3 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH4 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH5 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH6 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH7 }}, -}; -/** STM32F3 DMA1 device */ -dma_dev *DMA1 = &dma1; - -static dma_dev dma2 = { - .regs = DMA2_BASE, - .clk_id = RCC_DMA2, - .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH2 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH3 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH4 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH5 }}, -}; -/** STM32F3 DMA2 device */ -dma_dev *DMA2 = &dma2; - -/* - * Auxiliary routines - */ - -/* Can channel serve cfg->tube_req_src? */ -static int cfg_req_ok(dma_channel channel, dma_tube_config *cfg) { - return (cfg->tube_req_src & 0x7) == channel; -} - -/* Can dev serve cfg->tube_req_src? */ -static int cfg_dev_ok(dma_dev *dev, dma_tube_config *cfg) { - return (rcc_clk_id)(cfg->tube_req_src >> 3) == dev->clk_id; -} - -/* Is addr acceptable for use as DMA src/dst? */ -static int cfg_mem_ok(__io void *addr) { - enum dma_atype atype = _dma_addr_type(addr); - return atype == DMA_ATYPE_MEM || atype == DMA_ATYPE_PER; -} - -/* Is the direction implied by src->dst supported? */ -static int cfg_dir_ok(dma_tube_config *cfg) { - /* We can't do peripheral->peripheral transfers. */ - return ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) || - (_dma_addr_type(cfg->tube_dst) == DMA_ATYPE_MEM)); -} - -static int preconfig_check(dma_dev *dev, dma_channel channel, - dma_tube_config *cfg) { - if (!cfg_req_ok(channel, cfg)) { - return -DMA_TUBE_CFG_EREQ; - } - if (cfg->tube_nr_xfers > 65535) { - return -DMA_TUBE_CFG_ENDATA; - } - if (!cfg_dev_ok(dev, cfg)) { - return -DMA_TUBE_CFG_EDEV; - } - if (!cfg_mem_ok(cfg->tube_src)) { - return -DMA_TUBE_CFG_ESRC; - } - if (!cfg_mem_ok(cfg->tube_dst)) { - return -DMA_TUBE_CFG_EDST; - } - if (!cfg_dir_ok(cfg)) { - return -DMA_TUBE_CFG_EDIR; - } - return DMA_TUBE_CFG_SUCCESS; -} - -static inline void set_ccr(dma_tube_reg_map *chregs, - dma_xfer_size msize, int minc, - dma_xfer_size psize, int pinc, - uint32 other_flags) { - chregs->CCR = ((msize << 10) | (psize << 8) | - (minc ? DMA_CCR_MINC : 0) | (pinc ? DMA_CCR_PINC : 0) | - other_flags); -} - -static inline uint32 cfg_ccr_flags(unsigned tube_flags) { - /* DMA_CFG_SRC_INC and DMA_CFG_DST_INC are special */ - return tube_flags & ~(DMA_CFG_SRC_INC | DMA_CFG_DST_INC); -} - -/* Configure chregs according to cfg, where cfg->tube_dst is peripheral. */ -static int config_to_per(dma_tube_reg_map *chregs, dma_tube_config *cfg) { - /* Check that ->tube_src is memory (if it's anything else, we - * shouldn't have been called). */ - ASSERT(_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM); - - set_ccr(chregs, - cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC, - cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC, - (cfg_ccr_flags(cfg->tube_flags) | DMA_CCR_DIR_FROM_MEM)); - chregs->CNDTR = cfg->tube_nr_xfers; - chregs->CMAR = (uint32)cfg->tube_src; - chregs->CPAR = (uint32)cfg->tube_dst; - return DMA_TUBE_CFG_SUCCESS; -} - -/* Configure chregs according to cfg, where cfg->tube_dst is memory. */ -static int config_to_mem(dma_tube_reg_map *chregs, dma_tube_config *cfg) { - uint32 mem2mem; - - if ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) && - (cfg->tube_flags & DMA_CFG_CIRC)) { - /* Can't do mem-to-mem and circular mode */ - return -DMA_TUBE_CFG_ECFG; - } - - mem2mem = (_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM ? - DMA_CCR_MEM2MEM : 0); - set_ccr(chregs, - cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC, - cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC, - (cfg_ccr_flags(cfg->tube_flags) | - DMA_CCR_DIR_FROM_PER | - mem2mem)); - chregs->CNDTR = cfg->tube_nr_xfers; - chregs->CMAR = (uint32)cfg->tube_dst; - chregs->CPAR = (uint32)cfg->tube_src; - return DMA_TUBE_CFG_SUCCESS; -} - -/* - * Routines - */ - -int dma_tube_cfg(dma_dev *dev, dma_channel channel, dma_tube_config *cfg) { - dma_tube_reg_map *chregs; - int ret = preconfig_check(dev, channel, cfg); - - if (ret < 0) { - return ret; - } - - dma_disable(dev, channel); /* Must disable before reconfiguring */ - dma_clear_isr_bits(dev, channel); /* For sanity and consistency - * with STM32F2. */ - - chregs = dma_tube_regs(dev, channel); - switch (_dma_addr_type(cfg->tube_dst)) { - case DMA_ATYPE_PER: - ret = config_to_per(chregs, cfg); - break; - case DMA_ATYPE_MEM: - ret = config_to_mem(chregs, cfg); - break; - default: - /* Can't happen */ - ASSERT(0); - return -DMA_TUBE_CFG_ECFG; - } - if (ret < 0) { - return ret; - } - chregs->CNDTR = cfg->tube_nr_xfers; - return DMA_TUBE_CFG_SUCCESS; -} - -void dma_set_priority(dma_dev *dev, - dma_channel channel, - dma_priority priority) { - dma_channel_reg_map *channel_regs; - uint32 ccr; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - channel_regs = dma_channel_regs(dev, channel); - ccr = channel_regs->CCR; - ccr &= ~DMA_CCR_PL; - ccr |= (priority << 12); - channel_regs->CCR = ccr; -} - -void dma_set_num_transfers(dma_dev *dev, - dma_channel channel, - uint16 num_transfers) { - dma_channel_reg_map *channel_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - channel_regs = dma_channel_regs(dev, channel); - channel_regs->CNDTR = num_transfers; -} - -void dma_attach_interrupt(dma_dev *dev, dma_channel channel, - void (*handler)(void)) { - DMA_GET_HANDLER(dev, channel) = handler; - nvic_irq_enable(dev->handlers[channel - 1].irq_line); -} - -void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { - /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ - dma_channel_regs(dev, channel)->CCR &= ~0xF; - DMA_GET_HANDLER(dev, channel) = NULL; -} - -void dma_enable(dma_dev *dev, dma_channel channel) { - dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); - bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1); -} - -void dma_disable(dma_dev *dev, dma_channel channel) { - dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); - bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0); -} - -dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) { - /* Grab and clear the ISR bits. */ - uint8 status_bits = dma_get_isr_bits(dev, channel); - dma_clear_isr_bits(dev, channel); - - /* If the channel global interrupt flag is cleared, then - * something's very wrong. */ - ASSERT(status_bits & 0x1); - /* If GIF is set, then some other flag should be set, barring - * something unexpected (e.g. the user making an unforeseen IFCR - * write). */ - ASSERT(status_bits != 0x1); - - /* ISR flags get set even if the corresponding interrupt enable - * bits in the channel's configuration register are cleared, so we - * can't use a switch here. - * - * Don't change the order of these if statements. */ - if (status_bits & 0x8) { - return DMA_TRANSFER_ERROR; - } else if (status_bits & 0x2) { - return DMA_TRANSFER_COMPLETE; - } else if (status_bits & 0x4) { - return DMA_TRANSFER_HALF_COMPLETE; - } - - /* If we get here, one of our assumptions has been violated, but - * the debug level is too low for the above ASSERTs() to have had - * any effect. In order to fail fast, mimic the DMA controller's - * behavior when an error occurs. */ - dma_disable(dev, channel); - return DMA_TRANSFER_ERROR; -} - -void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { - dma_channel_reg_map *chan_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - chan_regs = dma_channel_regs(dev, channel); - chan_regs->CMAR = (uint32)addr; -} - -void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { - dma_channel_reg_map *chan_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - chan_regs = dma_channel_regs(dev, channel); - chan_regs->CPAR = (uint32)addr; -} - -/* - * IRQ handlers - */ - -void __irq_dma1_ch1(void) { - dma_irq_handler(DMA1, DMA_CH1); -} - -void __irq_dma1_ch2(void) { - dma_irq_handler(DMA1, DMA_CH2); -} - -void __irq_dma1_ch3(void) { - dma_irq_handler(DMA1, DMA_CH3); -} - -void __irq_dma1_ch4(void) { - dma_irq_handler(DMA1, DMA_CH4); -} - -void __irq_dma1_ch5(void) { - dma_irq_handler(DMA1, DMA_CH5); -} - -void __irq_dma1_ch6(void) { - dma_irq_handler(DMA1, DMA_CH6); -} - -void __irq_dma1_ch7(void) { - dma_irq_handler(DMA1, DMA_CH7); -} - -void __irq_dma2_ch1(void) { - dma_irq_handler(DMA2, DMA_CH1); -} - -void __irq_dma2_ch2(void) { - dma_irq_handler(DMA2, DMA_CH2); -} - -void __irq_dma2_ch3(void) { - dma_irq_handler(DMA2, DMA_CH3); -} - -void __irq_dma2_ch4(void) { - dma_irq_handler(DMA2, DMA_CH4); -} - -void __irq_dma2_ch5(void) { - dma_irq_handler(DMA2, DMA_CH5); -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_exti.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_exti.c deleted file mode 100644 index 44f0057..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_exti.c +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/stm32f3/exti.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 EXTI. - */ - -#include -#include -#include "exti_private.h" - -void exti_select(exti_num num, exti_cfg cfg) { - exti_do_select(&SYSCFG_BASE->EXTICR[num / 4], num, cfg); -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_fpu.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_fpu.c deleted file mode 100644 index 7ea5277..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_fpu.c +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/fpu.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 FPU. - */ - -#include - -void fpu_enable(void) { - /* - * set coprocessor access control registers - */ - asm("\tLDR.W R0, =0xE000ED88\n" - "\tLDR R1, [R0]\n" - "\tORR R1, R1, #(0xF << 20)\n" - "\tSTR R1, [R0]\n" - "\tDSB\n" - "\tISB"); -} - -void fpu_disable(void) { - /* - * clear coprocessor access control registers - */ - asm("\tLDR.W R0, =0xE000ED88\n" - "\tLDR R1, [R0]\n" - "\tORR R1, R1, #(0x0 << 20)\n" - "\tSTR R1, [R0]\n" - "\tDSB\n" - "\tISB"); -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_gpio.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_gpio.c deleted file mode 100644 index 45992a4..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_gpio.c +++ /dev/null @@ -1,169 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/gpio.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 GPIO. - */ - -#include -#include -#include - -/* - * GPIO devices - */ - -gpio_dev gpioa = { - .regs = GPIOA_BASE, - .clk_id = RCC_GPIOA, - .exti_port = EXTI_PA, -}; -/** GPIO port A device. */ -gpio_dev* const GPIOA = &gpioa; - -gpio_dev gpiob = { - .regs = GPIOB_BASE, - .clk_id = RCC_GPIOB, - .exti_port = EXTI_PB, -}; -/** GPIO port B device. */ -gpio_dev* const GPIOB = &gpiob; - -gpio_dev gpioc = { - .regs = GPIOC_BASE, - .clk_id = RCC_GPIOC, - .exti_port = EXTI_PC, -}; -/** GPIO port C device. */ -gpio_dev* const GPIOC = &gpioc; - -gpio_dev gpiod = { - .regs = GPIOD_BASE, - .clk_id = RCC_GPIOD, - .exti_port = EXTI_PD, -}; -/** GPIO port D device. */ -gpio_dev* const GPIOD = &gpiod; - -gpio_dev gpioe = { - .regs = GPIOE_BASE, - .clk_id = RCC_GPIOE, - .exti_port = EXTI_PE, -}; -/** GPIO port E device. */ -gpio_dev* const GPIOE = &gpioe; - -gpio_dev gpiof = { - .regs = GPIOF_BASE, - .clk_id = RCC_GPIOF, - .exti_port = EXTI_PF, -}; -/** GPIO port F device. */ -gpio_dev* const GPIOF = &gpiof; - -/* - * GPIO routines - */ - -/** - * Initialize and reset all available GPIO devices. - */ -void gpio_init_all(void) { - gpio_init(GPIOA); - gpio_init(GPIOB); - gpio_init(GPIOC); - gpio_init(GPIOD); - gpio_init(GPIOE); - gpio_init(GPIOF); -} - -/** - * @brief Set the mode of a GPIO pin. - * @param dev GPIO device. - * @param bit Bit on dev whose mode to set, 0--15. - * @param mode Mode to set the pin to. - * @param flags Flags to modify basic mode configuration - */ -void gpio_set_modef(gpio_dev *dev, - uint8 bit, - gpio_pin_mode mode, - unsigned flags) { - gpio_reg_map *regs = dev->regs; - unsigned shift = bit * 2; - uint32 tmp; - - /* Mode */ - tmp = regs->MODER; - tmp &= ~(0x3 << shift); - tmp |= mode << shift; - regs->MODER = tmp; - - /* Output type */ - bb_peri_set_bit(®s->OTYPER, bit, flags & 0x1); - - /* Speed */ - tmp = regs->OSPEEDR; - tmp &= ~(0x3 << shift); - tmp |= ((flags >> 1) & 0x3) << shift; - regs->OSPEEDR = tmp; - - /* Pull-up/pull-down */ - tmp = regs->PUPDR; - tmp &= ~(0x3 << shift); - tmp |= ((flags >> 3) & 0x3) << shift; - regs->PUPDR = tmp; -} - -/** - * @brief Set a pin's alternate function. - * - * The pin must have its mode set to GPIO_MODE_AF for this to take - * effect. - * - * @param dev Device whose pin to configure. - * @param bit Pin whose alternate function to set. - * @param af Alternate function to use for pin. - * @see gpio_set_modef() - */ -void gpio_set_af(gpio_dev *dev, uint8 bit, gpio_af af) { - __io uint32 *afr; - unsigned shift; - uint32 tmp; - if (bit >= 8) { - afr = &dev->regs->AFRH; - shift = 4 * (bit - 8); - } else{ - afr = &dev->regs->AFRL; - shift = 4 * bit; - } - tmp = *afr; - tmp &= ~(0xF << shift); - tmp |= (af << shift); - *afr = tmp; -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_i2c.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_i2c.c deleted file mode 100644 index 2412987..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_i2c.c +++ /dev/null @@ -1,319 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/i2c.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 I2C support - */ - -#include "i2c_private.h" -#include -#include - -/* - * Devices - */ - -/* on GPIO_AF_4 (PA14,PA15) (PB7,PB6) (PB9,PB8)*/ -static i2c_dev i2c1 = I2C_DEV_OLD(1, &gpiob, 7, 6); -/** STM32F3 I2C device 1 */ -i2c_dev* const I2C1 = &i2c1; - -/* on GPIO_AF_4 (PA10,PA9) (PF0,PF1) (PF0,PF6)*/ -static i2c_dev i2c2 = I2C_DEV_OLD(2, &gpioa, 10, 9); -/** STM32F3 I2C device 2 */ -i2c_dev* const I2C2 = &i2c2; - -/* - * Routines - */ - -void i2c_config_gpios(const i2c_dev *dev) { - gpio_set_modef(sda_port(dev), dev->sda_pin, GPIO_MODE_AF, GPIO_MODEF_TYPE_OD); - gpio_set_modef(scl_port(dev), dev->scl_pin, GPIO_MODE_AF, GPIO_MODEF_TYPE_OD); - - gpio_set_af(sda_port(dev), dev->sda_pin, GPIO_AF_4); - gpio_set_af(scl_port(dev), dev->scl_pin, GPIO_AF_4); -} - -void i2c_master_release_bus(const i2c_dev *dev) { - gpio_write_bit(scl_port(dev), dev->scl_pin, 1); /* TODO check this */ - gpio_write_bit(sda_port(dev), dev->sda_pin, 1); - - i2c_config_gpios(dev); -} - -int32 wait_for_state_change(i2c_dev *dev, - i2c_state state, - uint32 timeout) { - //FIXME not yet used on F3 - return 1; -} - -void i2c_bus_reset(const i2c_dev *dev) { - //FIXME not yet used on F3 -} - -void _i2c_software_reset(i2c_dev *dev) { - dev->regs->CR1 &= ~I2C_CR1_PE; - while(dev->regs->CR1 & I2C_CR1_PE) - ; - dev->regs->CR1 |= I2C_CR1_PE; -} - -void i2c_master_enable(i2c_dev *dev, uint32 flags) { - /* Bring the peripheral down for configuration */ - i2c_peripheral_disable(dev); - - /* Reset the bus when requested so */ - if (flags & I2C_BUS_RESET) - i2c_bus_reset(dev); - - /* Turn on the clock and set GPIO modes */ - i2c_init(dev); - i2c_config_gpios(dev); - - /* Configure analog and digital filters */ - /* TODO ANFOFF, DNF */ - - /* Configure the clock and rise time */ - dev->regs->TIMINGR = I2C_TIMING_10_kHz; - - /* Configure NOSTRETCH behaviour */ - /* TODO NOSTRETCH */ - - /* Enable all interrupts */ /* FIXME not yet used on F3 */ - //nvic_irq_enable(dev->ev_nvic_line); - //nvic_irq_enable(dev->er_nvic_line); - //i2c_enable_irq(dev, 0xFE); /* All interrupts */ - - /* Make it go! */ - i2c_peripheral_enable(dev); - - dev->state = I2C_STATE_IDLE; -} - -static void _i2c_master_xmit(i2c_dev *dev, i2c_msg *msg) { - uint32 cr2; - uint32 isr; - uint16 remaining = msg->length; - msg->xferred = 0; - uint8 *ptr = msg->data; /* pointer to data buffer */ - - while (remaining > 0) { - uint32 reload = remaining > 0xFF ? I2C_CR2_RELOAD : 0U; - uint16 size = remaining >= 0xFF ? 0xFF : remaining & 0xFF; - uint32 nbytes = size << I2C_CR2_NBYTES_SHIFT; - - cr2 = dev->regs->CR2; - cr2 &= ~(I2C_CR2_RELOAD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN); - cr2 |= reload | nbytes; - dev->regs->CR2 = cr2; - - if (msg->xferred == 0) /* first loop iteration? */ - dev->regs->CR2 |= I2C_CR2_START; /* generate START condition */ - - while (ptr < msg->data + msg->xferred + size) { - while ( !( (isr = dev->regs->ISR) & (I2C_ISR_NACKF | I2C_ISR_TXIS) ) ) - ; /* wait until ready for the next byte or NACK*/ - - if (isr & I2C_ISR_TXIS) - dev->regs->TXDR = *ptr++; /* byte to send */ - else { /* NACKF */ - dev->regs->ICR |= I2C_ICR_NACKCF; /* clear NACK flag */ - dev->regs->CR2 |= I2C_CR2_STOP; /* generate STOP condition */ - return; /* STOP condition is automatically generated */ - } - } - - if (reload) - while ( !(dev->regs->ISR & I2C_ISR_TCR) ) - ; /* wait for transmission reload complete */ - - remaining -= size; - msg->xferred += size; - } - - while ( !(dev->regs->ISR & I2C_ISR_TC) ) - ; /* wait for transmission complete */ - - dev->regs->CR2 |= I2C_CR2_STOP; /* generate STOP condition */ - - while ( !(dev->regs->ISR & I2C_ISR_STOPF) ) - ; /* wait for STOP flag */ - - dev->regs->ICR |= I2C_ICR_STOPCF; /* clear STOP flag */ -} - -static void _i2c_master_recv(i2c_dev *dev, i2c_msg *msg) { - uint32 cr2; - uint16 remaining = msg->length; - msg->xferred = 0; - uint8 *ptr = msg->data; /* pointer to data buffer */ - - while (remaining > 0) { - uint32 reload = remaining > 0xFF ? I2C_CR2_RELOAD : 0U; - uint16 size = remaining >= 0xFF ? 0xFF : remaining & 0xFF; - uint32 nbytes = size << I2C_CR2_NBYTES_SHIFT; - - cr2 = dev->regs->CR2; - cr2 &= ~(I2C_CR2_RELOAD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN); - cr2 |= reload | nbytes | I2C_CR2_RD_WRN; - dev->regs->CR2 = cr2; - - if (msg->xferred == 0) /* first loop iteration? */ - dev->regs->CR2 |= I2C_CR2_START; /* generate START condition */ - - while (ptr < msg->data + msg->xferred + size) { - while ( !(dev->regs->ISR & I2C_ISR_RXNE) ) - ; /* wait for next byte */ - - *ptr++ = dev->regs->RXDR & I2C_RXDR_RXDATA; /* read byte */ - } - - if (reload) - while ( !(dev->regs->ISR & I2C_ISR_TCR) ) - ; /* wait for transmission reload complete */ - - remaining -= size; - msg->xferred += size; - } - - while ( !(dev->regs->ISR & I2C_ISR_TC)) - ; /* wait for transmission complete */ - - dev->regs->CR2 |= I2C_CR2_STOP; /* generate STOP condition */ - - while ( !(dev->regs->ISR & I2C_ISR_STOPF) ) - ; /* wait for STOP flag */ - - dev->regs->ICR |= I2C_ICR_STOPCF; /* clear STOP flag */ -} - -int32 i2c_master_xfer(i2c_dev *dev, - i2c_msg *msgs, - uint16 num, - uint32 timeout) { - i2c_msg *msg; - - ASSERT(dev->state == I2C_STATE_IDLE); - - dev->msg = msgs; - dev->msgs_left = num; - dev->timestamp = systick_uptime(); /* FIXME implement handling of timeout */ - dev->state = I2C_STATE_BUSY; - - /* loop over messages */ - for (msg = dev->msg; dev->msgs_left; dev->msgs_left--, msg++) { - /* set slave address and direction*/ - uint32 addr = msg->flags & I2C_MSG_10BIT_ADDR - ? I2C_CR2_ADD10 | (msg->addr << I2C_CR2_SADD_10_BIT_SHIFT) - : msg->addr << I2C_CR2_SADD_7_BIT_SHIFT; - uint32 rd = msg->flags & I2C_MSG_READ ? I2C_CR2_RD_WRN : 0U; - uint32 cr2 = dev->regs->CR2; - cr2 &= ~(I2C_CR2_HEAD10R | I2C_CR2_ADD10 | I2C_CR2_SADD_10_BIT | I2C_CR2_RD_WRN); - cr2 |= rd | addr; - dev->regs->CR2 = cr2; - - if (rd) - _i2c_master_recv(dev, msg); - else - _i2c_master_xmit(dev, msg); - } - - dev->state = I2C_STATE_IDLE; - - return 0; /* FIXME implement error handling*/ -} - -void i2c_start_condition(i2c_dev *dev) { - dev->regs->CR2 |= I2C_CR2_START; /* generate START condition */ -} - -void i2c_stop_condition(i2c_dev *dev) { - dev->regs->CR2 |= I2C_CR2_STOP; /* generate STOP condition */ - - while ( !(dev->regs->ISR & I2C_ISR_STOPF) ) - ; /* wait for STOP flag */ - - dev->regs->ICR |= I2C_ICR_STOPCF; /* clear STOP flag */ -} - -void i2c_enable_irq(i2c_dev *dev, uint32 irqs) { - dev->regs->CR1 |= irqs; -} - -void i2c_disable_irq(i2c_dev *dev, uint32 irqs) { - dev->regs->CR1 &= ~irqs; -} - -/* ACK/NACK */ -void i2c_enable_ack(i2c_dev *dev) { - //FIXME nonexistant on F3 -} - -void i2c_disable_ack(i2c_dev *dev) { - //FIXME nonexistant on F3 -} - -void i2c_write(i2c_dev *dev, uint8 byte) { - //FIXME proper handling of ISR - dev->regs->TXDR = byte; -} - -uint8 i2c_read(i2c_dev *dev) { - //FIXME proper handling of ISR - return dev->regs->RXDR & I2C_RXDR_RXDATA; -} - -void _i2c_irq_handler(i2c_dev *dev) { - //FIXME not yet used on F3 -} - -void _i2c_irq_error_handler(i2c_dev *dev) { - //FIXME not yet used on F3 -} - -/* - * IRQ handlers - */ - -void __irq_i2c1_ev(void) { - _i2c_irq_handler(I2C1); -} - -void __irq_i2c2_ev(void) { - _i2c_irq_handler(I2C2); -} - -void __irq_i2c1_er(void) { - _i2c_irq_error_handler(I2C1); -} - -void __irq_i2c2_er(void) { - _i2c_irq_error_handler(I2C2); -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_opamp.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_opamp.c deleted file mode 100644 index c6ec0d5..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_opamp.c +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/opamp.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 OpAmp support. - */ - -#include - -/* - * Devices - */ - -static opamp_dev opamp1 = { .regs = OPAMP1_BASE }; const opamp_dev *OPAMP1 = &opamp1; -static opamp_dev opamp2 = { .regs = OPAMP2_BASE }; const opamp_dev *OPAMP2 = &opamp2; -static opamp_dev opamp3 = { .regs = OPAMP3_BASE }; const opamp_dev *OPAMP3 = &opamp3; -static opamp_dev opamp4 = { .regs = OPAMP4_BASE }; const opamp_dev *OPAMP4 = &opamp4; - -/* TODO - * actually implement me ;-) - */ diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_rcc.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_rcc.c deleted file mode 100644 index 4099e80..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_rcc.c +++ /dev/null @@ -1,149 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/rcc.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 RCC. - */ - -#include -#include -#include - -#include "rcc_private.h" - -#define APB1 RCC_APB1 -#define APB2 RCC_APB2 -#define AHB RCC_AHB - -/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset - * register bit numbers. */ -const struct rcc_dev_info rcc_dev_table[] = { - [RCC_GPIOA] = { .clk_domain = AHB, .line_num = RCC_AHBENR_IOPAEN_BIT }, - [RCC_GPIOB] = { .clk_domain = AHB, .line_num = RCC_AHBENR_IOPBEN_BIT }, - [RCC_GPIOC] = { .clk_domain = AHB, .line_num = RCC_AHBENR_IOPCEN_BIT }, - [RCC_GPIOD] = { .clk_domain = AHB, .line_num = RCC_AHBENR_IOPDEN_BIT }, - [RCC_GPIOE] = { .clk_domain = AHB, .line_num = RCC_AHBENR_IOPEEN_BIT }, - [RCC_GPIOF] = { .clk_domain = AHB, .line_num = RCC_AHBENR_IOPFEN_BIT }, - - [RCC_ADC12] = { .clk_domain = AHB, .line_num = RCC_AHBENR_ADC12EN_BIT}, -#if STM32_F3_LINE == STM32_F3_LINE_303 - [RCC_ADC34] = { .clk_domain = AHB, .line_num = RCC_AHBENR_ADC34EN_BIT }, -#endif - - [RCC_DAC] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_DACEN_BIT }, - - [RCC_DMA1] = { .clk_domain = AHB, .line_num = RCC_AHBENR_DMA1EN_BIT }, - [RCC_DMA2] = { .clk_domain = AHB, .line_num = RCC_AHBENR_DMA2EN_BIT }, - - [RCC_I2C1] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_I2C1EN_BIT }, - [RCC_I2C2] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_I2C2EN_BIT }, - - [RCC_SPI1] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_SPI1EN_BIT }, - [RCC_SPI2] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_SPI2EN_BIT }, - [RCC_SPI3] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_SPI3EN_BIT }, - - [RCC_USART1] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_USART1EN_BIT }, - [RCC_USART2] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_USART2EN_BIT }, - [RCC_USART3] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_USART3EN_BIT }, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - [RCC_UART4] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_UART4EN_BIT }, - [RCC_UART5] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_UART5EN_BIT }, -#endif - - [RCC_TIMER1] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_TIM1EN_BIT }, - [RCC_TIMER2] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_TIM2EN_BIT }, - [RCC_TIMER3] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_TIM3EN_BIT }, - [RCC_TIMER4] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_TIM4EN_BIT }, - [RCC_TIMER6] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_TIM6EN_BIT }, -#if STM32_F3_LINE == STM32_F3_LINE_303 - [RCC_TIMER7] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_TIM7EN_BIT }, - [RCC_TIMER8] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_TIM8EN_BIT }, -#endif - [RCC_TIMER15] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_TIM15EN_BIT }, - [RCC_TIMER16] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_TIM16EN_BIT }, - [RCC_TIMER17] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_TIM17EN_BIT }, - - [RCC_SYSCFG] = { .clk_domain = APB2, .line_num = RCC_APB2ENR_SYSCFGEN_BIT }, - [RCC_PWR] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_PWREN_BIT }, - [RCC_CRC] = { .clk_domain = AHB, .line_num = RCC_AHBENR_CRCEN_BIT }, - [RCC_FLITF] = { .clk_domain = AHB, .line_num = RCC_AHBENR_FLITFEN_BIT }, - [RCC_SRAM] = { .clk_domain = AHB, .line_num = RCC_AHBENR_SRAMEN_BIT }, - [RCC_USB] = { .clk_domain = APB1, .line_num = RCC_APB1ENR_USBEN_BIT }, -}; - -/* pll_cfg->data must point to a valid struct stm32f3_rcc_pll_data. */ -void rcc_configure_pll(rcc_pll_cfg *pll_cfg) { - stm32f3_rcc_pll_data *data = pll_cfg->data; - rcc_pll_multiplier pll_mul = data->pll_mul; - rcc_prediv_divider pclk_prediv = data->pclk_prediv; //TODO use this!!! - uint32 cfgr; - uint32 cfgr2; - - /* Check that the PLL is disabled. */ - ASSERT_FAULT(!rcc_is_clk_on(RCC_CLK_PLL)); - - cfgr2 = RCC_BASE->CFGR2; - cfgr2 &= ~(RCC_CFGR2_PREDIV); - cfgr2 |= pclk_prediv; - RCC_BASE->CFGR2 = cfgr2; - - cfgr = RCC_BASE->CFGR; - cfgr &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL); - cfgr |= pll_cfg->pllsrc | pll_mul; - RCC_BASE->CFGR = cfgr; -} - -void rcc_clk_enable(rcc_clk_id id) { - static __io uint32* enable_regs[] = { - [APB1] = &RCC_BASE->APB1ENR, - [APB2] = &RCC_BASE->APB2ENR, - [AHB] = &RCC_BASE->AHBENR, - }; - rcc_do_clk_enable(enable_regs, id); -} - -void rcc_reset_dev(rcc_clk_id id) { - static __io uint32* reset_regs[] = { - [APB1] = &RCC_BASE->APB1RSTR, - [APB2] = &RCC_BASE->APB2RSTR, - [AHB] = &RCC_BASE->AHBRSTR, - }; - rcc_do_reset_dev(reset_regs, id); -} - -void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { - static const uint32 masks[] = { - [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE, - [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1, - [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2, - [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE, - }; - rcc_do_set_prescaler(masks, prescaler, divider); -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_spi.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_spi.c deleted file mode 100644 index 3fafa52..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_spi.c +++ /dev/null @@ -1,143 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/spi.c - * @author Marti Bolivar , - * F3-port by Hanspeter Portner - * @brief STM32F3 SPI/I2S. - */ - -#include -#include -#include "spi_private.h" - -/* - * Devices - */ - -static spi_dev spi1 = SPI_DEV(1); -static spi_dev spi2 = SPI_DEV(2); -static spi_dev spi3 = SPI_DEV(3); - -spi_dev *SPI1 = &spi1; -spi_dev *SPI2 = &spi2; -spi_dev *SPI3 = &spi3; - -/* - * Routines - */ - -void spi_config_gpios(spi_dev *dev, - uint8 as_master, - gpio_dev *nss_dev, - uint8 nss_bit, - gpio_dev *comm_dev, - uint8 sck_bit, - uint8 miso_bit, - uint8 mosi_bit) { - gpio_set_modef(nss_dev, nss_bit, GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(comm_dev, sck_bit, GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(comm_dev, miso_bit, GPIO_MODE_AF, GPIO_MODEF_PUPD_NONE); - gpio_set_modef(comm_dev, mosi_bit, GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - - if ( (dev == SPI1) || (dev == SPI2) ) - { - gpio_set_af(nss_dev, nss_bit, GPIO_AF_5); - gpio_set_af(comm_dev, sck_bit, GPIO_AF_5); - gpio_set_af(comm_dev, miso_bit, GPIO_AF_5); - gpio_set_af(comm_dev, mosi_bit, GPIO_AF_5); - } - else if (dev == SPI3) - { - gpio_set_af(nss_dev, nss_bit, GPIO_AF_6); - gpio_set_af(comm_dev, sck_bit, GPIO_AF_6); - gpio_set_af(comm_dev, miso_bit, GPIO_AF_6); - gpio_set_af(comm_dev, mosi_bit, GPIO_AF_6); - } -} - -void spi_foreach(void (*fn)(spi_dev*)) { - fn(SPI1); - fn(SPI2); - fn(SPI3); -} - -void spi_data_size(struct spi_dev *dev, spi_ds ds) { - uint8 byte_frame = ds <= SPI_DATA_SIZE_8_BIT; - uint32 cr2 = dev->regs->CR2; - cr2 &= ~(SPI_CR2_DS | SPI_CR2_FRXTH); - cr2 |= ds; - if (byte_frame) - cr2 |= SPI_CR2_FRXTH; - dev->regs->CR2 = cr2; -} - -/* - * SPI auxiliary routines - */ -void spi_reconfigure(spi_dev *dev, uint32 cr1_config) { - spi_irq_disable(dev, SPI_INTERRUPTS_ALL); - spi_peripheral_disable(dev); - - uint8 byte_frame = (dev->regs->CR2 & SPI_CR2_DS) <= SPI_DATA_SIZE_8_BIT; - uint32 cr2 = dev->regs->CR2; - cr2 &= ~SPI_CR2_FRXTH; - if (byte_frame) - cr2 |= SPI_CR2_FRXTH; - dev->regs->CR2 = cr2; - - dev->regs->CR1 = cr1_config; - spi_peripheral_enable(dev); -} - -uint16 spi_rx_reg(spi_dev *dev) { - uint8 byte_frame = (dev->regs->CR2 & SPI_CR2_DS) <= SPI_DATA_SIZE_8_BIT; - if (byte_frame) { - __io uint8 *dr8 = (__io uint8 *)&dev->regs->DR; /* we need to access as byte */ - return (uint16)*dr8; - } else { - __io uint16 *dr16 = (__io uint16 *)&dev->regs->DR; /* we need to access as half-word */ - return (uint16)*dr16; - } -} - -uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) { - uint32 txed = 0; - uint8 byte_frame = (dev->regs->CR2 & SPI_CR2_DS) <= SPI_DATA_SIZE_8_BIT; - while (spi_is_tx_empty(dev) && (txed < len)) { - if (byte_frame) { - __io uint8 *dr8 = (__io uint8 *)&dev->regs->DR; /* we need to access as byte */ - *dr8 = ((const uint8 *)buf)[txed++]; - } else { - __io uint16 *dr16 = (__io uint16 *)&dev->regs->DR; /* we need to access as half-word */ - *dr16 = ((const uint16 *)buf)[txed++]; - } - } - return txed; -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_syscfg.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_syscfg.c deleted file mode 100644 index 9421b2d..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_syscfg.c +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/syscfg.c - * @author F3-port by Hanspeter Portner - * @brief SYSCFG routines. - */ - -#include -#include -#include - -void syscfg_set_mem_mode(syscfg_mem_mode mode) { - uint32 memrmp = SYSCFG_BASE->CFGR1; - memrmp &= ~SYSCFG_CFGR1_MEM_MODE; - memrmp |= (uint32)mode; - SYSCFG_BASE->CFGR1 = memrmp; -} diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_timer.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_timer.c deleted file mode 100644 index 08b9063..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_timer.c +++ /dev/null @@ -1,147 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/timer.c - * @author Marti Bolivar , - * F3-port by Hanspeter Portner - * @brief STM32F3 timer. - */ - -#include -#include -#include -#include "timer_private.h" - -/** - * @brief Get the GPIO alternate function corresponding to a timer. - * - * For example, if dev is TIMER1, this function returns - * GPIO_AF_TIM_1_2. This is useful for e.g. using gpio_set_af() to set - * a pin's alternate function to a timer. - * - * @param dev Timer device, must not be TIMER6 or TIMER7. - * @return gpio_af corresponding to dev - * @see gpio_set_af - * @see gpio_af - */ - /* FIXME this has to be inline with the PIN_MAP, but some timers are accessible on different alternate function lanes based on the used pin... */ -gpio_af timer_get_af(timer_dev *dev) { - rcc_clk_id clk_id = dev->clk_id; - /* Timers 6 and 7 don't have any capture/compare, so they can't do - * PWM (and in fact have no AF values). */ - ASSERT(clk_id != RCC_TIMER6 && clk_id != RCC_TIMER7); - switch(dev->clk_id) { - case RCC_TIMER1: - return GPIO_AF_6; - case RCC_TIMER2: // fall-through - case RCC_TIMER3: // fall-through - case RCC_TIMER4: - return GPIO_AF_2; - case RCC_TIMER8: - return GPIO_AF_4; - case RCC_TIMER15: - return GPIO_AF_3; - case RCC_TIMER16: // fall-through - case RCC_TIMER17: - return GPIO_AF_1; - default: - ASSERT(0); // Can't happen - return (gpio_af)-1; - } -} - -/* - * IRQ handlers - * - * Defer to the timer_private dispatch API. - * - * FIXME: The names of these handlers are inaccurate since XL-density - * devices came out. Update these to match the STM32F3 names, maybe - * using some weak symbol magic to preserve backwards compatibility if - * possible. Once that's done, we can just move the IRQ handlers into - * the top-level libmaple/timer.c, and there will be no need for this - * file. - */ - -void __irq_tim1_brk_tim15(void) { - dispatch_adv_brk(TIMER1); - dispatch_tim_9_12(TIMER15); -} - -void __irq_tim1_up_tim16(void) { - dispatch_adv_up(TIMER1); - dispatch_tim_10_11_13_14(TIMER16); -} - -void __irq_tim1_trg_com_tim17(void) { - dispatch_adv_trg_com(TIMER1); - dispatch_tim_10_11_13_14(TIMER17); -} - -void __irq_tim1_cc(void) { - dispatch_adv_cc(TIMER1); -} - -void __irq_tim2(void) { - dispatch_general(TIMER2); -} - -void __irq_tim3(void) { - dispatch_general(TIMER3); -} - -void __irq_tim4(void) { - dispatch_general(TIMER4); -} - -void __irq_tim6_dacunder(void) { - dispatch_basic(TIMER6); - /* FIXME handle DAC12 underrun */ -} - -#if STM32_F3_LINE == STM32_F3_LINE_303 -void __irq_tim7(void) { - dispatch_basic(TIMER7); -} - -void __irq_tim8_brk(void) { - dispatch_adv_brk(TIMER8); -} - -void __irq_tim8_up(void) { - dispatch_adv_up(TIMER8); -} - -void __irq_tim8_trg_com(void) { - dispatch_adv_trg_com(TIMER8); -} - -void __irq_tim8_cc(void) { - dispatch_adv_cc(TIMER8); -} -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/f3_usart.c b/STM32F3/cores/maple/libmaple/stm32f3/f3_usart.c deleted file mode 100644 index 4d466b3..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/f3_usart.c +++ /dev/null @@ -1,210 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/usart.c - * @author F3-port by Hanspeter Portner - * @brief STM32F3 USART. - */ - -#include -#include -#include -#include "usart_private.h" - -/* - * Devices - */ - -static ring_buffer usart1_rb; -static usart_dev usart1 = { - .regs = USART1_BASE, - .rb = &usart1_rb, - .max_baud = 4500000UL, - .clk_id = RCC_USART1, - .irq_num = NVIC_USART1, -}; -/** USART1 device */ -usart_dev *USART1 = &usart1; - -static ring_buffer usart2_rb; -static usart_dev usart2 = { - .regs = USART2_BASE, - .rb = &usart2_rb, - .max_baud = 2250000UL, - .clk_id = RCC_USART2, - .irq_num = NVIC_USART2, -}; -/** USART2 device */ -usart_dev *USART2 = &usart2; - -static ring_buffer usart3_rb; -static usart_dev usart3 = { - .regs = USART3_BASE, - .rb = &usart3_rb, - .max_baud = 2250000UL, - .clk_id = RCC_USART3, - .irq_num = NVIC_USART3, -}; -/** USART3 device */ -usart_dev *USART3 = &usart3; - -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -static ring_buffer uart4_rb; -static usart_dev uart4 = { - .regs = UART4_BASE, - .rb = &uart4_rb, - .max_baud = 2250000UL, - .clk_id = RCC_UART4, - .irq_num = NVIC_UART4, -}; -/** UART4 device */ -usart_dev *UART4 = &uart4; - -static ring_buffer uart5_rb; -static usart_dev uart5 = { - .regs = UART5_BASE, - .rb = &uart5_rb, - .max_baud = 2250000UL, - .clk_id = RCC_UART5, - .irq_num = NVIC_UART5, -}; -/** UART5 device */ -usart_dev *UART5 = &uart5; -#endif - -/* - * Routines - */ - -void usart_config_gpios_async(usart_dev *udev, - gpio_dev *rx_dev, uint8 rx, - gpio_dev *tx_dev, uint8 tx, - unsigned flags) { - gpio_af af = usart_get_af(udev); - gpio_set_modef(rx_dev, rx, GPIO_MODE_AF, GPIO_MODEF_PUPD_NONE); - //gpio_set_modef(tx_dev, tx, GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(tx_dev, tx, GPIO_MODE_AF, GPIO_MODEF_TYPE_OD); - gpio_set_af(rx_dev, rx, af); - gpio_set_af(tx_dev, tx, af); -} - -void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) { - /* Figure out the clock speed, if the user doesn't give one. */ - if (clock_speed == 0) { - clock_speed = _usart_clock_freq(dev); - } - ASSERT(clock_speed); - - uint32 divider = clock_speed / baud; - uint32 tmpreg = clock_speed % baud; - /* round divider : if fractional part i greater than 0.5 increment divider */ - if (tmpreg >= baud / 2) - divider++; - dev->regs->BRR = (uint16)divider; -} - -uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len) { - usart_reg_map *regs = dev->regs; - uint32 txed = 0; - while ((regs->SR & USART_SR_TXE) && (txed < len)) { - regs->TDR = buf[txed++] & USART_TDR_TDR; - } - return txed; -} - -/** - * @brief Call a function on each USART. - * @param fn Function to call. - */ -void usart_foreach(void (*fn)(usart_dev*)) { - fn(USART1); - fn(USART2); - fn(USART3); -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - fn(UART4); - fn(UART5); -#endif -} - -/** - * @brief Get GPIO alternate function mode for a USART. - * @param dev USART whose gpio_af to get. - * @return gpio_af corresponding to dev. - */ -gpio_af usart_get_af(usart_dev *dev) { - switch (dev->clk_id) { - case RCC_USART1: - case RCC_USART2: - case RCC_USART3: - return GPIO_AF_7; -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - case RCC_UART4: - case RCC_UART5: - return GPIO_AF_5; -#endif - default: - ASSERT(0); /* Can't happen */ - return (gpio_af)-1; - } -} - -/* - * Interrupt handlers. - */ - -static __always_inline void usart_irq(ring_buffer *rb, usart_reg_map *regs) { -#ifdef USART_SAFE_INSERT - /* If the buffer is full and the user defines USART_SAFE_INSERT, - * ignore new bytes. */ - rb_safe_insert(rb, regs->RDR & USART_RDR_RDR); -#else - /* By default, push bytes around in the ring buffer. */ - rb_push_insert(rb, regs->RDR & USART_RDR_RDR); -#endif -} - -void __irq_usart1(void) { - usart_irq(&usart1_rb, USART1_BASE); -} - -void __irq_usart2(void) { - usart_irq(&usart2_rb, USART2_BASE); -} - -void __irq_usart3(void) { - usart_irq(&usart3_rb, USART3_BASE); -} - -#ifdef STM32_HIGH_DENSITY -void __irq_uart4(void) { - usart_irq(&uart4_rb, UART4_BASE); -} - -void __irq_uart5(void) { - usart_irq(&uart5_rb, UART5_BASE); -} -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/adc.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/adc.h deleted file mode 100644 index 76422f6..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/adc.h +++ /dev/null @@ -1,696 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/adc.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 ADC support. - */ - -#ifndef _LIBMAPLE_STM32F3_ADC_H_ -#define _LIBMAPLE_STM32F3_ADC_H_ - -#include -#include -#include /* For the prescalers */ - -/* - * Register map - */ - -/* - * ADC individual register map type. - */ -typedef struct adc_reg_map { - __io uint32 ISR; /**< */ - __io uint32 IER; /**< */ - __io uint32 CR; /**< */ - __io uint32 CFGR; /**< */ - uint32 reserved1; - __io uint32 SMPR1; /**< */ - __io uint32 SMPR2; /**< */ - uint32 reserved2; - __io uint32 TR1; /**< */ - __io uint32 TR2; /**< */ - __io uint32 TR3; /**< */ - uint32 reserved3; - __io uint32 SQR1; /**< */ - __io uint32 SQR2; /**< */ - __io uint32 SQR3; /**< */ - __io uint32 SQR4; /**< */ - __io uint32 DR; /**< */ - uint32 reserved4 [2]; - __io uint32 JSQR; /**< */ - uint32 reserved5 [4]; - __io uint32 OFR1; /**< */ - __io uint32 OFR2; /**< */ - __io uint32 OFR3; /**< */ - __io uint32 OFR4; /**< */ - uint32 reserved6 [4]; - __io uint32 JDR1; /**< */ - __io uint32 JDR2; /**< */ - __io uint32 JDR3; /**< */ - __io uint32 JDR4; /**< */ - uint32 reserved7 [4]; - __io uint32 AWD2CR; /**< */ - __io uint32 AWD3CR; /**< */ - uint32 reserved8 [2]; - __io uint32 DIFSEL; /**< */ - __io uint32 CALFACT; /**< */ -} adc_reg_map; - -/* - * ADC master and slave common register map type. - */ -typedef struct adc_common_reg_map { - __io uint32 CSR; /**< */ - uint32 reserved; - __io uint32 CCR; /**< */ - __io uint32 CDR; /**< */ -} adc_common_reg_map; - -/** ADC device type. */ -typedef struct adc_dev { - adc_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - adc_private_data *priv; /**< ADC private data */ -} adc_dev; - -/* - * Devices - */ - -extern const struct adc_dev *ADC1; /* master */ -extern const struct adc_dev *ADC2; /* slave */ -#if STM32_F3_LINE == STM32_F3_LINE_303 -extern const struct adc_dev *ADC3; /* master */ -extern const struct adc_dev *ADC4; /* slave */ -#endif - -/* - * Register map base pointers - */ - -/** STM32F3 ADC1 individual register map base pointer. */ -#define ADC1_BASE ((struct adc_reg_map*)0x50000000) -/** STM32F3 ADC2 individual register map base pointer. */ -#define ADC2_BASE ((struct adc_reg_map*)0x50000100) -/** STM32F3 ADC1/ADC2 common register map base pointer. */ -#define ADC12_BASE ((struct adc_common_reg_map*)0x50000300) -#if STM32_F3_LINE == STM32_F3_LINE_303 -/** STM32F3 ADC3 individual register map base pointer. */ -#define ADC3_BASE ((struct adc_reg_map*)0x50000400) -/** STM32F3 ADC4 individual register map base pointer. */ -#define ADC4_BASE ((struct adc_reg_map*)0x50000500) -/** STM32F3 ADC3/ADC4 common register map base pointer. */ -#define ADC34_BASE ((struct adc_common_reg_map*)0x50000700) -#endif - -/* - * Register bit definitions - */ - -/* Interrupt and status register */ -#define ADC_ISR_JQOVF_BIT 10 -#define ADC_ISR_AWD3_BIT 9 -#define ADC_ISR_AWD2_BIT 8 -#define ADC_ISR_AWD1_BIT 7 -#define ADC_ISR_JEOS_BIT 6 -#define ADC_ISR_JEOC_BIT 5 -#define ADC_ISR_OVR_BIT 4 -#define ADC_ISR_EOS_BIT 3 -#define ADC_ISR_EOC_BIT 2 -#define ADC_ISR_EOSMP_BIT 1 -#define ADC_ISR_ADRDY_BIT 0 - -#define ADC_ISR_JQOVF (1U << ADC_ISR_JQOVF_BIT) -#define ADC_ISR_AWD3 (1U << ADC_ISR_AWD3_BIT) -#define ADC_ISR_AWD2 (1U << ADC_ISR_AWD2_BIT) -#define ADC_ISR_AWD1 (1U << ADC_ISR_AWD1_BIT) -#define ADC_ISR_JEOS (1U << ADC_ISR_JEOS_BIT) -#define ADC_ISR_JEOC (1U << ADC_ISR_JEOC_BIT) -#define ADC_ISR_OVR (1U << ADC_ISR_OVR_BIT) -#define ADC_ISR_EOS (1U << ADC_ISR_EOS_BIT) -#define ADC_ISR_EOC (1U << ADC_ISR_EOC_BIT) -#define ADC_ISR_EOSMP (1U << ADC_ISR_EOSMP_BIT) -#define ADC_ISR_ADRDY (1U << ADC_ISR_ADRDY_BIT) - -/* FIXME make an enum out of this */ -#define ADC_WATCHDOG_1_INTERRUPT ADC_ISR_AWD1 -#define ADC_WATCHDOG_2_INTERRUPT ADC_ISR_AWD2 -#define ADC_WATCHDOG_3_INTERRUPT ADC_ISR_AWD3 -#define ADC_CONV_INTERRUPT ADC_ISR_EOC -#define ADC_INJ_CONV_INTERRUPT ADC_ISR_JEOC -#define ADC_OVERRUN_INTERRUPT ADC_ISR_OVR -#define ADC_ALL_INTERRUPTS (ADC_CONV_INTERRUPT | ADC_WATCHDOG_1_INTERRUPT | ADC_WATCHDOG_2_INTERRUPT | ADC_WATCHDOG_3_INTERRUPT | ADC_INJ_CONV_INTERRUPT | ADC_OVERRUN_INTERRUPT) - -/* Interrupt enable register */ -#define ADC_IER_JQOVF_BIT 10 -#define ADC_IER_AWD3_BIT 9 -#define ADC_IER_AWD2_BIT 8 -#define ADC_IER_AWD1_BIT 7 -#define ADC_IER_JEOS_BIT 6 -#define ADC_IER_JEOC_BIT 5 -#define ADC_IER_OVR_BIT 4 -#define ADC_IER_EOS_BIT 3 -#define ADC_IER_EOC_BIT 2 -#define ADC_IER_EOSMP_BIT 1 -#define ADC_IER_ADRDY_BIT 0 - -#define ADC_IER_JQOVF (1U << ADC_IER_JQOVF_BIT) -#define ADC_IER_AWD3 (1U << ADC_IER_AWD3_BIT) -#define ADC_IER_AWD2 (1U << ADC_IER_AWD2_BIT) -#define ADC_IER_AWD1 (1U << ADC_IER_AWD1_BIT) -#define ADC_IER_JEOS (1U << ADC_IER_JEOS_BIT) -#define ADC_IER_JEOC (1U << ADC_IER_JEOC_BIT) -#define ADC_IER_OVR (1U << ADC_IER_OVR_BIT) -#define ADC_IER_EOS (1U << ADC_IER_EOS_BIT) -#define ADC_IER_EOC (1U << ADC_IER_EOC_BIT) -#define ADC_IER_EOSMP (1U << ADC_IER_EOSMP_BIT) -#define ADC_IER_ADRDY (1U << ADC_IER_ADRDY_BIT) - -/* Control register */ -#define ADC_CR_ADCAL_BIT 31 -#define ADC_CR_ADCALDIF_BIT 30 -#define ADC_CR_ADVREGEN_SHIFT 28 -#define ADC_CR_JADSTP_BIT 5 -#define ADC_CR_ADSTP_BIT 4 -#define ADC_CR_JADSTART_BIT 3 -#define ADC_CR_ADSTART_BIT 2 -#define ADC_CR_ADDIS_BIT 1 -#define ADC_CR_ADEN_BIT 0 - -#define ADC_CR_ADCAL (1U << ADC_CR_ADCAL_BIT) -#define ADC_CR_ADCALDIF (1U << ADC_CR_ADCALDIF_BIT) -#define ADC_CR_ADVREGEN (0x3 << ADC_CR_ADVREGEN_SHIFT) -#define ADC_CR_ADVREGEN_ENABLE (0x1 << ADC_CR_ADVREGEN_SHIFT) -#define ADC_CR_ADVREGEN_DISABLE (0x2 << ADC_CR_ADVREGEN_SHIFT) -#define ADC_CR_JADSTP (1U << ADC_CR_JADSTP_BIT) -#define ADC_CR_ADSTP (1U << ADC_CR_ADSTP_BIT) -#define ADC_CR_JADSTART (1U << ADC_CR_JADSTART_BIT) -#define ADC_CR_ADSTART (1U << ADC_CR_ADSTART_BIT) -#define ADC_CR_ADDIS (1U << ADC_CR_ADDIS_BIT) -#define ADC_CR_ADEN (1U << ADC_CR_ADEN_BIT) - -/* Configuration register */ -#define ADC_CFGR_AWD1CH_SHIFT 26 -#define ADC_CFGR_JAUTO_BIT 25 -#define ADC_CFGR_JAWD1EN_BIT 24 -#define ADC_CFGR_AWD1EN_BIT 23 -#define ADC_CFGR_AWD1SGL_BIT 22 -#define ADC_CFGR_JQM_BIT 21 -#define ADC_CFGR_JDISCEN_BIT 20 -#define ADC_CFGR_JDISCNUM_SHIFT 17 -#define ADC_CFGR_DISCEN_BIT 16 -#define ADC_CFGR_AUTDLY_BIT 14 -#define ADC_CFGR_CONT_BIT 13 -#define ADC_CFGR_OVRMOD_BIT 12 -#define ADC_CFGR_EXTEN_SHIFT 10 -#define ADC_CFGR_EXTSEL_SHIFT 6 -#define ADC_CFGR_ALIGN_BIT 5 -#define ADC_CFGR_RES_SHIFT 3 -#define ADC_CFGR_DMACFG_BIT 1 -#define ADC_CFGR_DMAEN_BIT 0 - -#define ADC_CFGR_AWD1CH (0x1F << ADC_CFGR_AWD1CH_SHIFT) -#define ADC_CFGR_JAUTO (1U << ADC_CFGR_JAUTO_BIT) -#define ADC_CFGR_JAWD1EN (1U << ADC_CFGR_JAWD1EN_BIT) -#define ADC_CFGR_AWD1EN (1U << ADC_CFGR_AWD1EN_BIT) -#define ADC_CFGR_AWD1SGL (1U << ADC_CFGR_AWD1SGL_BIT) -#define ADC_CFGR_JQM (1U << ADC_CFGR_JQM_BIT) -#define ADC_CFGR_JDISCEN (1U << ADC_CFGR_JDISCEN_BIT) -#define ADC_CFGR_JDISCNUM (0x7 << ADC_CFGR_JDISCNUM_SHIFT) -#define ADC_CFGR_DISCEN (1U << ADC_CFGR_DISCEN_BIT) -#define ADC_CFGR_AUTODLY (1U << ADC_CFGR_AUTODLY_BIT) -#define ADC_CFGR_CONT (1U << ADC_CFGR_CONT_BIT) -#define ADC_CFGR_OVRMOD (1U << ADC_CFGR_OVRMOD_BIT) -#define ADC_CFGR_EXTEN (0x3 << ADC_CFGR_EXTEN_SHIFT) -#define ADC_CFGR_EXTSEL (0xF << ADC_CFGR_EXTSEL_SHIFT) -#define ADC_CFGR_ALIGN (1U << ADC_CFGR_ALIGN_BIT) -#define ADC_CFGR_RES (0x3 << ADC_CFGR_RES_SHIFT) -#define ADC_CFGR_DMACFG (1U << ADC_CFGR_DMACFG_BIT) -#define ADC_CFGR_DMAEN (1U << ADC_CFGR_DMAEN_BIT) - -/* Sample time register 1 */ -#define ADC_SMPR1_SMP9 (0x7 << 27) -#define ADC_SMPR1_SMP8 (0x7 << 24) -#define ADC_SMPR1_SMP7 (0x7 << 21) -#define ADC_SMPR1_SMP6 (0x7 << 18) -#define ADC_SMPR1_SMP5 (0x7 << 15) -#define ADC_SMPR1_SMP4 (0x7 << 12) -#define ADC_SMPR1_SMP3 (0x7 << 9) -#define ADC_SMPR1_SMP2 (0x7 << 6) -#define ADC_SMPR1_SMP1 (0x7 << 3) - -/* Sample time register 2 */ -#define ADC_SMPR2_SMP18 (0x7 << 24) -#define ADC_SMPR2_SMP17 (0x7 << 21) -#define ADC_SMPR2_SMP16 (0x7 << 18) -#define ADC_SMPR2_SMP15 (0x7 << 15) -#define ADC_SMPR2_SMP14 (0x7 << 12) -#define ADC_SMPR2_SMP13 (0x7 << 9) -#define ADC_SMPR2_SMP12 (0x7 << 6) -#define ADC_SMPR2_SMP11 (0x7 << 3) -#define ADC_SMPR2_SMP10 0x7 - -/* Analog watchdog 1 threshold register */ -#define ADC_TR1_HT1 (0xFFF << 16) /* 12bit watchdog */ -#define ADC_TR1_LT1 0xFFF - -/* Analog watchdog 2 threshold register */ -#define ADC_TR2_HT2 (0xFF << 16) /* 8bit watchdog */ -#define ADC_TR2_LT2 0xFF - -/* Analog watchdog 3 threshold register */ -#define ADC_TR3_HT3 (0xFF << 16) /* 8bit watchdog */ -#define ADC_TR3_LT3 0xFF - -/* Regular sequence register 1 */ -#define ADC_SQR1_SQ4 (0x1F << 24) -#define ADC_SQR1_SQ3 (0x1F << 18) -#define ADC_SQR1_SQ2 (0x1F << 12) -#define ADC_SQR1_SQ1 (0x1F << 6) -#define ADC_SQR1_L 0xF - -/* Regular sequence register 2 */ -#define ADC_SQR2_SQ9 (0x1F << 24) -#define ADC_SQR2_SQ8 (0x1F << 18) -#define ADC_SQR2_SQ7 (0x1F << 12) -#define ADC_SQR2_SQ6 (0x1F << 6) -#define ADC_SQR2_SQ5 0x1F - -/* Regular sequence register 3 */ -#define ADC_SQR3_SQ14 (0x1F << 24) -#define ADC_SQR3_SQ13 (0x1F << 18) -#define ADC_SQR3_SQ12 (0x1F << 12) -#define ADC_SQR3_SQ11 (0x1F << 6) -#define ADC_SQR3_SQ10 0x1F - -/* Regular sequence register 4 */ -#define ADC_SQR4_SQ16 (0x1F << 6) -#define ADC_SQR4_SQ15 0x1F - -/* Regular data register */ -#define ADC_DR_RDATA 0xFFFF - -/* Injected sequence register */ -#define ADC_JSQR_JEXTEN_SHIFT 6 -#define ADC_JSQR_JEXTSEL_SHIFT 2 - -#define ADC_JSQR_SQ4 (0x1F << 26) -#define ADC_JSQR_SQ3 (0x1F << 20) -#define ADC_JSQR_SQ2 (0x1F << 14) -#define ADC_JSQR_SQ1 (0x1F << 8) -#define ADC_JSQR_JEXTEN (0x3 << ADC_JSQR_JEXTEN_SHIFT) -#define ADC_JSQR_JEXTSEL (0xF << ADC_JSQR_JEXTSEL_SHIFT) -#define ADC_JSQR_JL 0x3 - -/* Offset register 1 */ -#define ADC_OFR1_OFFSET1EN_BIT 31 - -#define ADC_OFR1_OFFSET1ENT (1U << ADC_OFR1_OFFSET1EN_BIT) -#define ADC_OFR1_OFFSET1_CH (0x1F << 26) -#define ADC_OFR1_OFFSET1 0xFFF - -/* Offset register 2 */ -#define ADC_OFR2_OFFSET2EN_BIT 31 - -#define ADC_OFR2_OFFSET2EN (1U << ADC_OFR2_OFFSET2EN_BIT) -#define ADC_OFR2_OFFSET2_CH (0x1F << 26) -#define ADC_OFR2_OFFSET2 0xFFF - -/* Offset register 3 */ -#define ADC_OFR3_OFFSET3EN_BIT 31 - -#define ADC_OFR3_OFFSET3EN (1U << ADC_OFR3_OFFSET3EN_BIT) -#define ADC_OFR3_OFFSET3_CH (0x1F << 26) -#define ADC_OFR3_OFFSET3 0xFFF - -/* Offset register 4 */ -#define ADC_OFR4_OFFSET4EN_BIT 31 - -#define ADC_OFR4_OFFSET4EN (1U << ADC_OFR4_OFFSET4EN_BIT) -#define ADC_OFR4_OFFSET4_CH (0x1F << 26) -#define ADC_OFR4_OFFSET4 0xFFF - -/* Injected data register 1 */ -#define ADC_JDR1_JDATA1 0xFFFF - -/* Injected data register 2 */ -#define ADC_JDR2_JDATA2 0xFFFF - -/* Injected data register 3 */ -#define ADC_JDR3_JDATA3 0xFFFF - -/* Injected data register 4 */ -#define ADC_JDR4_JDATA4 0xFFFF - -/* Analog watchdog 2 configuration register */ -#define ADC_AWD2CR_AWD2CH (0x1FFFF << 1) - -/* Analog watchdog 3 configuration register */ -#define ADC_AWD3CR_AWD3CH (0x1FFFF << 1) - -/* Differential mode selection register */ -#define ADC_DIFSEL_DIFSEL (0x1FFFF << 1) - -/* Calibration factors */ -#define ADC_CALFACT_CALFACT_D (0x7F << 16) -#define ADC_CALFACT_CALFACT_S 0x7F - -/* Common status register */ -#define ADC_CSR_JQOVF_SLV_BIT 26 -#define ADC_CSR_AWD3_SLV_BIT 25 -#define ADC_CSR_AWD2_SLV_BIT 24 -#define ADC_CSR_AWD1_SLV_BIT 23 -#define ADC_CSR_JEOS_SLV_BIT 22 -#define ADC_CSR_JEOC_SLV_BIT 21 -#define ADC_CSR_OVR_SLV_BIT 20 -#define ADC_CSR_EOS_SLV_BIT 19 -#define ADC_CSR_EOC_SLV_BIT 18 -#define ADC_CSR_EOSMP_SLV_BIT 17 -#define ADC_CSR_ADRDY_SLV_BIT 16 - -#define ADC_CSR_JQOVF_MST_BIT 10 -#define ADC_CSR_AWD3_MST_BIT 9 -#define ADC_CSR_AWD2_MST_BIT 8 -#define ADC_CSR_AWD1_MST_BIT 7 -#define ADC_CSR_JEOS_MST_BIT 6 -#define ADC_CSR_JEOC_MST_BIT 5 -#define ADC_CSR_OVR_MST_BIT 4 -#define ADC_CSR_EOS_MST_BIT 3 -#define ADC_CSR_EOC_MST_BIT 2 -#define ADC_CSR_EOSMP_MST_BIT 1 -#define ADC_CSR_ADRDY_MST_BIT 0 - -#define ADC_CSR_JQOVF_SLV (1U << ADC_CSR_JQOVF_SLV_BIT) -#define ADC_CSR_AWD3_SLV (1U << ADC_CSR_AWD3_SLV_BIT) -#define ADC_CSR_AWD2_SLV (1U << ADC_CSR_AWD2_SLV_BIT) -#define ADC_CSR_AWD1_SLV (1U << ADC_CSR_AWD1_SLV_BIT) -#define ADC_CSR_JEOS_SLV (1U << ADC_CSR_JEOS_SLV_BIT) -#define ADC_CSR_JEOC_SLV (1U << ADC_CSR_JEOC_SLV_BIT) -#define ADC_CSR_OVR_SLV (1U << ADC_CSR_OVR_SLV_BIT) -#define ADC_CSR_EOS_SLV (1U << ADC_CSR_EOS_SLV_BIT) -#define ADC_CSR_EOC_SLV (1U << ADC_CSR_EOC_SLV_BIT) -#define ADC_CSR_EOSMP_SLV (1U << ADC_CSR_EOS_MP_SLV_BIT) -#define ADC_CSR_ADRDY_SLV (1U << ADC_CSR_ADRDY_SLV_BIT) - -#define ADC_CSR_JQOVF_MST (1U << ADC_CSR_JQOVF_MST_BIT) -#define ADC_CSR_AWD3_MST (1U << ADC_CSR_AWD3_MST_BIT) -#define ADC_CSR_AWD2_MST (1U << ADC_CSR_AWD2_MST_BIT) -#define ADC_CSR_AWD1_MST (1U << ADC_CSR_AWD1_MST_BIT) -#define ADC_CSR_JEOS_MST (1U << ADC_CSR_JEOS_MST_BIT) -#define ADC_CSR_JEOC_MST (1U << ADC_CSR_JEOC_MST_BIT) -#define ADC_CSR_OVR_MST (1U << ADC_CSR_OVR_MST_BIT) -#define ADC_CSR_EOS_MST (1U << ADC_CSR_EOS_MST_BIT) -#define ADC_CSR_EOC_MST (1U << ADC_CSR_EOC_MST_BIT) -#define ADC_CSR_EOSMP_MST (1U << ADC_CSR_EOS_MP_MST_BIT) -#define ADC_CSR_ADRDY_MST (1U << ADC_CSR_ADRDY_MST_BIT) - -/* Common control register */ -#define ADC_CCR_VBATEN_BIT 24 -#define ADC_CCR_TSEN_BIT 23 -#define ADC_CCR_VREFEN_BIT 22 -#define ADC_CCR_CKMODE_SHIFT 16 -#define ADC_CCR_MDMA_SHIFT 14 -#define ADC_CCR_DMACFG_BIT 13 -#define ADC_CCR_DELAY_SHIFT 8 -#define ADC_CCR_DUAL_SHIFT 0 - -#define ADC_CCR_VBATEN (1U << ADC_CCR_VBATEN_BIT) -#define ADC_CCR_TSEN (1U << ADC_CCR_TSEN_BIT) -#define ADC_CCR_VREFEN (1U << ADC_CCR_VREFEN_BIT) -#define ADC_CCR_CKMODE (0x3 << ADC_CCR_CKMODE_SHIFT) -#define ADC_CCR_MDMA (0x3 << ADC_CCR_MDMA_SHIFT) -#define ADC_CCR_DMACFG (1U << ADC_CCR_DMACFG_BIT) -#define ADC_CCR_DELAY (0xF << ADC_CCR_DELAY_SHIFT) -#define ADC_CCR_DUAL 0X1F - -/* Common regular data register for dual mode */ -#define ADC_CDR_RDATA_SLV (0xFFFF << 16) -#define ADC_CDR_RDATA_MST 0xFFFF - -/* - * Other types - */ - -/** - * @brief STM32F3 external event selectors for regular group - * conversion. - * - * For ease of use, each event selector is given along with the ADCs - * it's available on, along with any other availability restrictions. - * - * @see adc_set_extsel() - */ -typedef enum adc_extsel_event { - /* ADC1 (master) and ADC2 (slave) regular channels */ - ADC12_EXT_EV_TIM1_CC1 = 0x0 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM1_CC2 = 0x1 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM1_CC3 = 0x2 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM2_CC2 = 0x3 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM3_TRGO = 0x4 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM4_CC4 = 0x5 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_EXTI_11 = 0x6 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM8_TRGO = 0x7 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM8_TRGO2 = 0x8 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM1_TRGO = 0x9 << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM1_TRGO2 = 0xA << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM2_TRGO = 0xB << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM4_TRGO = 0xC << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM6_TRGO = 0xD << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM15_TRGO = 0xE << ADC_CFGR_EXTSEL_SHIFT, - ADC12_EXT_EV_TIM3_CC4 = 0xF << ADC_CFGR_EXTSEL_SHIFT, - - /* ADC1 (master) and ADC2 (slave) injected channels */ - ADC12_JEXT_EV_TIM1_TRGO = 0x0 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM1_CC4 = 0x1 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM2_TRGO = 0x2 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM2_CC1 = 0x3 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM3_CC4 = 0x4 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM4_TRGO = 0x5 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_EXTI_15 = 0x6 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM8_CC4 = 0x7 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM1_TRGO2 = 0x8 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM8_TRGO = 0x9 << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM8_TRGO2 = 0xA << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM3_CC3 = 0xB << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM3_TRGO = 0xC << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM3_CC1 = 0xD << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM6_TRGO = 0xE << ADC_JSQR_JEXTSEL_SHIFT, - ADC12_JEXT_EV_TIM15_TRGO = 0xF << ADC_JSQR_JEXTSEL_SHIFT, - - /* ADC3 (master) and ADC4 (slave) injected channels */ - ADC34_EXT_EV_TIM3_CC1 = 0x0 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM3_CC3 = 0x1 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM1_cc3 = 0x2 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM8_CC1 = 0x3 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM8_TRGO = 0x4 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_EXTI_2 = 0x5 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM4_CC1 = 0x6 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM2_TRGO = 0x7 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM8_TRGO2 = 0x8 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM1_TRGO = 0x9 << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM1_TRGO2 = 0xA << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM3_TRGO = 0xB << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM4_TRGO = 0xC << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM7_TRGO = 0xD << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM15_TRGO = 0xE << ADC_CFGR_EXTSEL_SHIFT, - ADC34_EXT_EV_TIM2_CC1 = 0xF << ADC_CFGR_EXTSEL_SHIFT, - - /* ADC3 (master) and ADC4 (slave) injected channels */ - ADC34_JEXT_EV_TIM1_TRGO = 0x0 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM1_CC4 = 0x1 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM4_CC3 = 0x2 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM8_CC2 = 0x3 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM8_CC4 = 0x4 << ADC_JSQR_JEXTSEL_SHIFT, - /* ADC34_JEXT_EV_TIM4_CC3 = 0x5 << ADC_JSQR_JEXTSEL_SHIFT, */ /* FIXME duplicate or typo in manual? */ - ADC34_JEXT_EV_TIM4_CC4 = 0x6 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM4_TRGO = 0x7 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM1_TRGO2 = 0x8 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM8_TRGO = 0x9 << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM8_TRGO2 = 0xA << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM1_CC3 = 0xB << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM3_TRGO = 0xC << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM2_TRGO = 0xD << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM7_TRGO = 0xE << ADC_JSQR_JEXTSEL_SHIFT, - ADC34_JEXT_EV_TIM15_TRGO = 0xF << ADC_JSQR_JEXTSEL_SHIFT, -} adc_extsel_event; - -/** - * @brief STM32F3 ADC trigger mode. - * - * These control the trigger mode of the ADC, which can be set to: - * Software trigger, hardware trigger on rising, falling or both edges. - */ -typedef enum adc_exttrig_mode { - ADC_EXTTRIG_MODE_SOFTWARE = 0x0 << ADC_CFGR_EXTEN_SHIFT, /**< .. */ - ADC_EXTTRIG_MODE_HARDWARE_RISING = 0x1 << ADC_CFGR_EXTEN_SHIFT, /**< .. */ - ADC_EXTTRIG_MODE_HARDWARE_FALLING = 0x2 << ADC_CFGR_EXTEN_SHIFT, /**< .. */ - ADC_EXTTRIG_MODE_HARDWARE_BOTH = 0x3 << ADC_CFGR_EXTEN_SHIFT, /**< .. */ -} adc_exttrig_mode; - -/** - * @brief STM32F3 ADC resolution. - * - * These control the ADC resolution, which can be set to: - * 6, 8, 10 or 12 bit. - */ -typedef enum adc_resolution { - ADC_RESOLUTION_12_BIT = 0x0 << ADC_CFGR_RES_SHIFT, /**< .. */ - ADC_RESOLUTION_10_BIT = 0x1 << ADC_CFGR_RES_SHIFT, /**< .. */ - ADC_RESOLUTION_8_BIT = 0x2 << ADC_CFGR_RES_SHIFT, /**< .. */ - ADC_RESOLUTION_6_BIT = 0x3 << ADC_CFGR_RES_SHIFT, /**< .. */ -} adc_resolution; - -/** - * @brief STM32F3 sample times, in ADC clock cycles. - * - * These control the amount of time spent sampling the input voltage. - */ -typedef enum adc_smp_rate { - ADC_SMPR_1_5 = 0x0, /**< 1.5 ADC cycles */ - ADC_SMPR_2_5 = 0x1, /**< 2.5 ADC cycles */ - ADC_SMPR_4_5 = 0x2, /**< 4.5 ADC cycles */ - ADC_SMPR_7_5 = 0x3, /**< 7.5 ADC cycles */ - ADC_SMPR_19_5 = 0x4, /**< 19.5 ADC cycles */ - ADC_SMPR_61_5 = 0x5, /**< 61.5 ADC cycles */ - ADC_SMPR_181_5 = 0x6, /**< 181.5 ADC cycles */ - ADC_SMPR_601_5 = 0x7, /**< 601.5 ADC cycles */ -} adc_smp_rate; - -/* - * FIXME SHIFT - */ - -/** - * @brief STM32F3 ADC clock mode. - */ -typedef enum adc_clock_mode { - ADC_CLOCK_MODE_ASYNCHRONOUS = 0x0, /**< . */ - ADC_CLOCK_MODE_SYNCHRONOUS_DIV_1 = 0x1, /**< . */ - ADC_CLOCK_MODE_SYNCHRONOUS_DIV_2 = 0x2, /**< . */ - ADC_CLOCK_MODE_SYNCHRONOUS_DIV_4 = 0x3, /**< . */ -} adc_clock_mode; - -/** - * @brief STM32F3 ADC DMA mode. - */ -typedef enum adc_dma_mode { - ADC_MDMA_MODE_DISABLE = (0x0 << ADC_CCR_MDMA_SHIFT), /**< . */ - ADC_MDMA_MODE_ENABLE_12_10_BIT = (0x2 << ADC_CCR_MDMA_SHIFT), /**< . */ - ADC_MDMA_MODE_ENABLE_8_6_BIT = (0x3 << ADC_CCR_MDMA_SHIFT), /**< . */ -} adc_dma_mode; - -/** - * @brief STM32F3 ADC mode. - */ -typedef enum adc_mode { - ADC_MODE_INDEPENDENT = 0x0, /**< . */ - ADC_MODE_DUAL_REGULAR_INJECTED = 0x1, /**< . */ - ADC_MODE_DUAL_REGULAR_ALTERNATE_TRIGGER = 0x2, /**< . */ - ADC_MODE_DUAL_INJECTED_ONLY = 0x5, /**< . */ - ADC_MODE_DUAL_REGULAR_ONLY = 0x6, /**< . */ - ADC_MODE_DUAL_INTERLEAVED_ONLY = 0x7, /**< . */ - ADC_MODE_DUAL_ALTERNATE_TRIGGER_ONLY = 0x9, /**< . */ -} adc_mode; - -/** - * @brief STM32F3 ADC prescalers, as divisors of PCLK2. - */ -typedef enum adc_prescaler { - /** ADC clock disabled, AHB clock enabled */ - ADC_PRE_AHBCLK_DIV_1 = ADC_CLOCK_MODE_SYNCHRONOUS_DIV_1, - ADC_PRE_AHBCLK_DIV_2 = ADC_CLOCK_MODE_SYNCHRONOUS_DIV_2, - ADC_PRE_AHBCLK_DIV_4 = ADC_CLOCK_MODE_SYNCHRONOUS_DIV_4, - - /** ADC clock enabled, AHB clock disabled */ - ADC_PRE_PCLK_DIV_1 = RCC_ADCPRE_PCLK_DIV_1, /** PCLK divided by 1 */ - ADC_PRE_PCLK_DIV_2 = RCC_ADCPRE_PCLK_DIV_2, /** PCLK divided by 2 */ - ADC_PRE_PCLK_DIV_4 = RCC_ADCPRE_PCLK_DIV_4, /** PCLK divided by 4 */ - ADC_PRE_PCLK_DIV_6 = RCC_ADCPRE_PCLK_DIV_6, /** PCLK divided by 6 */ - ADC_PRE_PCLK_DIV_8 = RCC_ADCPRE_PCLK_DIV_8, /** PCLK divided by 8 */ - ADC_PRE_PCLK_DIV_10 = RCC_ADCPRE_PCLK_DIV_10, /** PCLK divided by 10 */ - ADC_PRE_PCLK_DIV_12 = RCC_ADCPRE_PCLK_DIV_12, /** PCLK divided by 12 */ - ADC_PRE_PCLK_DIV_16 = RCC_ADCPRE_PCLK_DIV_16, /** PCLK divided by 16 */ - ADC_PRE_PCLK_DIV_32 = RCC_ADCPRE_PCLK_DIV_32, /** PCLK divided by 32 */ - ADC_PRE_PCLK_DIV_64 = RCC_ADCPRE_PCLK_DIV_64, /** PCLK divided by 64 */ - ADC_PRE_PCLK_DIV_128 = RCC_ADCPRE_PCLK_DIV_128, /** PCLK divided by 128 */ - ADC_PRE_PCLK_DIV_256 = RCC_ADCPRE_PCLK_DIV_256, /** PCLK divided by 256 */ -} adc_prescaler; - -/* - * Routines - */ - -/** - * @brief Calibrate an ADC peripheral - * - * Availability: STM32F1, STM32F3. - * - * @param dev adc device - */ -void adc_calibrate(const adc_dev *dev); - -/** - * @brief Set external trigger conversion mode event for regular channels - * - * Availability: STM32F1, STM32F3. - * - * @param dev ADC device - * @param mode external trigger disabled, on rising edge, on falling edge or on both - */ -void adc_set_exttrig(const adc_dev *dev, adc_exttrig_mode mode); - -/** - * @brief Set ADC resolution of an ADC peripheral - * - * Availability: STM32F3. - * - * @param dev adc device - * @param resolution ADC resolution (6, 8, 10 or 12 bit) - */ -void adc_set_resolution(const adc_dev *dev, adc_resolution res); - -/** - * @brief Enable the voltage regulatr of an ADC peripheral - * - * Availability: STM32F3. - * - * @param dev adc device - */ -void adc_regulator_enable(const adc_dev *dev); - -/** - * @brief Disable the voltage regulatr of an ADC peripheral - * - * Availability: STM32F3. - * - * @param dev adc device - */ -void adc_regulator_disable(const adc_dev *dev); - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/bkp.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/bkp.h deleted file mode 100644 index 3a49a41..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/bkp.h +++ /dev/null @@ -1,62 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/bkp.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 backup register support. - */ - -#ifndef _LIBMAPLE_STM32F3_BKP_H_ -#define _LIBMAPLE_STM32F3_BKP_H_ - -#define BKP_NR_DATA_REGS 16 - -/** Backup peripheral register map type. */ -typedef struct bkp_reg_map { - __io uint32 DR0; ///< Data register 0 - __io uint32 DR1; ///< Data register 1 - __io uint32 DR2; ///< Data register 2 - __io uint32 DR3; ///< Data register 3 - __io uint32 DR4; ///< Data register 4 - __io uint32 DR5; ///< Data register 5 - __io uint32 DR6; ///< Data register 6 - __io uint32 DR7; ///< Data register 7 - __io uint32 DR8; ///< Data register 8 - __io uint32 DR9; ///< Data register 9 - __io uint32 DR10; ///< Data register 10 - __io uint32 DR11; ///< Data register 11 - __io uint32 DR12; ///< Data register 12 - __io uint32 DR13; ///< Data register 13 - __io uint32 DR14; ///< Data register 14 - __io uint32 DR15; ///< Data register 15 -} bkp_reg_map; - -/** Backup peripheral register map base pointer. */ -#define BKP_BASE ((struct bkp_reg_map*)0x40002850) //is part of RTC memory map - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/comp.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/comp.h deleted file mode 100644 index ca40a96..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/comp.h +++ /dev/null @@ -1,119 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/comp.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Comparator support. - */ - -#ifndef _LIBMAPLE_STM32F3_COMP_H_ -#define _LIBMAPLE_STM32F3_COMP_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Register map - */ - -/* - * COMP individual register map type. - */ -typedef struct comp_reg_map { - __io uint32 CSR; /**< */ -} comp_reg_map; - -/** COMP device type. */ -typedef struct comp_dev { - comp_reg_map *regs; /**< Register map */ -} comp_dev; - -/* - * Devices - */ - -extern const struct comp_dev *COMP1; /* comparator 1 */ -extern const struct comp_dev *COMP2; /* comparator 2 */ -extern const struct comp_dev *COMP3; /* comparator 3 */ -extern const struct comp_dev *COMP4; /* comparator 4 */ -extern const struct comp_dev *COMP5; /* comparator 5 */ -extern const struct comp_dev *COMP6; /* comparator 6 */ -extern const struct comp_dev *COMP7; /* comparator 7 */ - -/* - * Register map base pointers - */ - -#define COMP1_BASE ((struct comp_reg_map*)0x4001001C) -#define COMP2_BASE ((struct comp_reg_map*)0x40010020) -#define COMP3_BASE ((struct comp_reg_map*)0x40010024) -#define COMP4_BASE ((struct comp_reg_map*)0x40010028) -#define COMP5_BASE ((struct comp_reg_map*)0x4001002C) -#define COMP6_BASE ((struct comp_reg_map*)0x40010030) -#define COMP7_BASE ((struct comp_reg_map*)0x40010034) - -/* - * Register bit definitions - */ - -/* Control and status register */ -#define COMP_CSR_LOCK_BIT 31 -#define COMP_CSR_OUT_BIT 30 -#define COMP_CSR_BLANKING_SHIFT 18 -#define COMP_CSR_HIST_SHIFT 16 -#define COMP_CSR_POL_BIT 15 -#define COMP_CSR_OUTSEL_SHIFT 10 -#define COMP_CSR_WINMODE_BIT 9 -#define COMP_CSR_INPSEL_BIT 7 -#define COMP_CSR_INMSEL_SHIFT 4 -#define COMP_CSR_MODE_SHIFT 2 -#define COMP_CSR_EN_BIT 0 - -#define COMP_CSR_LOCK (1U << COMP_CSR_LOCK_BIT) -#define COMP_CSR_OUT (1U << COMP_CSR_OUT_BIT) -#define COMP_CSR_BLANKING (0x7 << COMP_CSR_BLANKING_SHIFT) -#define COMP_CSR_HIST (0x3 << COMP_CSR_HIST_SHIFT) -#define COMP_CSR_POL (1U << COMP_CSR_POL_BIT) -#define COMP_CSR_OUTSEL (0xF << COMP_CSR_OUTSEL_SHIFT) -#define COMP_CSR_WINMODE (0xF << COMP_CSR_WINMODE_SHIFT) -#define COMP_CSR_INPSEL (1U << COMP_CSR_INPSEL_BIT) -#define COMP_CSR_INMSEL (0x7 << COMP_CSR_INMSEL_SHIFT) -#define COMP_CSR_MODE (0x3 << COMP_CSR_MODE_SHIFT) -#define COMP_CSR_EN (1U << COMP_CSR_EN_BIT) - -/* TODO - * actually implement me ;-) - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/crc.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/crc.h deleted file mode 100644 index 72e7995..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/crc.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/crc.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Cylic Redundancy Check (CRC) support. - */ - -#ifndef _LIBMAPLE_STM32F3_CRC_H_ -#define _LIBMAPLE_STM32F3_CRC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - * Register maps - */ - -/** CRC register map type */ -typedef struct crc_reg_map { - __io uint32 DR; /**< Data register */ - __io uint32 IDR; /**< Independent data register */ - __io uint32 CR; /**< Control register */ - uint32 reserved; - __io uint32 INIT; /**< Initial data register */ - __io uint32 POL; /**< Polynomial register */ -} crc_reg_map; - -/* - * Register map base pointers - */ - -/** CRC register map base pointer */ -#define CRC_BASE ((struct crc_reg_map*)0x40013800) //TODO - -/* - * Register bit definitions - */ - -/* Data register */ -#define CRC_DR_DATA 0xFFFFFFFF - -/* Independent data register */ -#define CRC_IDR_DATA 0xFF - -/* Control register */ -#define CRC_CR_REV_OUT_BIT 7 -#define CRC_CR_REV_IN_SHIFT 5 -#define CRC_CR_POLYSIZE_SHIFT 3 -#define CRC_CR_RESET_BIT 0 - -#define CRC_CR_REV_OUT (1U << CRC_CR_REV_OUT_BIT) -#define CRC_CR_REV_IN (0x3 << CRC_CR_REV_IN_SHIFT) -#define CRC_CR_POLYSIZE (0x3 << CRC_CR_POLYSIZE_SHIFT) -#define CRC_CR_RESET (1U << CRC_CR_RESET_BIT) - -/* Initial data register */ -#define CRC_INIT_DATA 0xFFFFFFFF - -/* Polynomial register */ -#define CRC_POL_DATA 0xFFFFFFFF - -/* TODO add some routines */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/dac.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/dac.h deleted file mode 100644 index 7c5e8f5..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/dac.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/dac.h - * @brief STM32F3 DAC support - */ - -#ifndef _LIBMAPLE_STM32F3_DAC_H_ -#define _LIBMAPLE_STM32F3_DAC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/** STM32F3 DAC register map type. */ -typedef struct dac_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 SWTRIGR; /**< Software trigger register */ - __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data - holding register */ - __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data - holding register */ - __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data - holding register */ - __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data - holding register */ - __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data - holding register */ - __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data - holding register */ - __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data - holding register */ - __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data - holding register */ - __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding - register */ - __io uint32 DOR1; /**< Channel 1 data output register */ - __io uint32 DOR2; /**< Channel 2 data output register */ -} dac_reg_map; - -//#define DAC1_BASE ((struct dac_reg_map*)0x40007400) -//#define DAC2_BASE ((struct dac_reg_map*)0x40009800) //TODO STM32F37/38xx - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/dma.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/dma.h deleted file mode 100644 index 9bb3b1b..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/dma.h +++ /dev/null @@ -1,557 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * Copyright (c) 2012 LeafLabs, LLC - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/dma.h - * @author Marti Bolivar , - * Original implementation by Michael Hope, - * F3-port by Hanspeter Portner - * @brief STM32F3 DMA series header. - */ - -#ifndef _LIBMAPLE_STM32F3_DMA_H_ -#define _LIBMAPLE_STM32F3_DMA_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -/* - * Register maps and base pointers - */ - -/** - * @brief STM32F3 DMA register map type. - * - * Note that DMA controller 2 (register map base pointer DMA2_BASE) - * only supports channels 1--5. - */ -typedef struct dma_reg_map { - __io uint32 ISR; /**< Interrupt status register */ - __io uint32 IFCR; /**< Interrupt flag clear register */ - __io uint32 CCR1; /**< Channel 1 configuration register */ - __io uint32 CNDTR1; /**< Channel 1 number of data register */ - __io uint32 CPAR1; /**< Channel 1 peripheral address register */ - __io uint32 CMAR1; /**< Channel 1 memory address register */ - const uint32 RESERVED1; /**< Reserved. */ - __io uint32 CCR2; /**< Channel 2 configuration register */ - __io uint32 CNDTR2; /**< Channel 2 number of data register */ - __io uint32 CPAR2; /**< Channel 2 peripheral address register */ - __io uint32 CMAR2; /**< Channel 2 memory address register */ - const uint32 RESERVED2; /**< Reserved. */ - __io uint32 CCR3; /**< Channel 3 configuration register */ - __io uint32 CNDTR3; /**< Channel 3 number of data register */ - __io uint32 CPAR3; /**< Channel 3 peripheral address register */ - __io uint32 CMAR3; /**< Channel 3 memory address register */ - const uint32 RESERVED3; /**< Reserved. */ - __io uint32 CCR4; /**< Channel 4 configuration register */ - __io uint32 CNDTR4; /**< Channel 4 number of data register */ - __io uint32 CPAR4; /**< Channel 4 peripheral address register */ - __io uint32 CMAR4; /**< Channel 4 memory address register */ - const uint32 RESERVED4; /**< Reserved. */ - __io uint32 CCR5; /**< Channel 5 configuration register */ - __io uint32 CNDTR5; /**< Channel 5 number of data register */ - __io uint32 CPAR5; /**< Channel 5 peripheral address register */ - __io uint32 CMAR5; /**< Channel 5 memory address register */ - const uint32 RESERVED5; /**< Reserved. */ - __io uint32 CCR6; /**< Channel 6 configuration register */ - __io uint32 CNDTR6; /**< Channel 6 number of data register */ - __io uint32 CPAR6; /**< Channel 6 peripheral address register */ - __io uint32 CMAR6; /**< Channel 6 memory address register */ - const uint32 RESERVED6; /**< Reserved. */ - __io uint32 CCR7; /**< Channel 7 configuration register */ - __io uint32 CNDTR7; /**< Channel 7 number of data register */ - __io uint32 CPAR7; /**< Channel 7 peripheral address register */ - __io uint32 CMAR7; /**< Channel 7 memory address register */ - const uint32 RESERVED7; /**< Reserved. */ -} dma_reg_map; - -/** DMA controller 1 register map base pointer */ -#define DMA1_BASE ((struct dma_reg_map*)0x40020000) -/** DMA controller 2 register map base pointer */ -#define DMA2_BASE ((struct dma_reg_map*)0x40020400) - -/** - * @brief STM32F3 DMA channel (i.e. tube) register map type. - * Provides access to an individual channel's registers. - * @see dma_tube_regs() - */ -typedef struct dma_tube_reg_map { - __io uint32 CCR; /**< Channel configuration register */ - __io uint32 CNDTR; /**< Channel number of data register */ - __io uint32 CPAR; /**< Channel peripheral address register */ - __io uint32 CMAR; /**< Channel memory address register */ -} dma_tube_reg_map; - -/** DMA1 channel 1 register map base pointer */ -#define DMA1CH1_BASE ((struct dma_tube_reg_map*)0x40020008) -/** DMA1 channel 2 register map base pointer */ -#define DMA1CH2_BASE ((struct dma_tube_reg_map*)0x4002001C) -/** DMA1 channel 3 register map base pointer */ -#define DMA1CH3_BASE ((struct dma_tube_reg_map*)0x40020030) -/** DMA1 channel 4 register map base pointer */ -#define DMA1CH4_BASE ((struct dma_tube_reg_map*)0x40020044) -/** DMA1 channel 5 register map base pointer */ -#define DMA1CH5_BASE ((struct dma_tube_reg_map*)0x40020058) -/** DMA1 channel 6 register map base pointer */ -#define DMA1CH6_BASE ((struct dma_tube_reg_map*)0x4002006C) -/** DMA1 channel 7 register map base pointer */ -#define DMA1CH7_BASE ((struct dma_tube_reg_map*)0x40020080) - -/** DMA2 channel 1 register map base pointer */ -#define DMA2CH1_BASE ((struct dma_tube_reg_map*)0x40020408) -/** DMA2 channel 2 register map base pointer */ -#define DMA2CH2_BASE ((struct dma_tube_reg_map*)0x4002041C) -/** DMA2 channel 3 register map base pointer */ -#define DMA2CH3_BASE ((struct dma_tube_reg_map*)0x40020430) -/** DMA2 channel 4 register map base pointer */ -#define DMA2CH4_BASE ((struct dma_tube_reg_map*)0x40020444) -/** DMA2 channel 5 register map base pointer */ -#define DMA2CH5_BASE ((struct dma_tube_reg_map*)0x40020458) - -/* - * Register bit definitions - */ - -/* Interrupt status register */ - -#define DMA_ISR_TEIF_BIT 3 -#define DMA_ISR_HTIF_BIT 2 -#define DMA_ISR_TCIF_BIT 1 -#define DMA_ISR_GIF_BIT 0 - -#define DMA_ISR_TEIF (1 << DMA_ISR_TEIF_BIT) -#define DMA_ISR_HTIF (1 << DMA_ISR_HTIF_BIT) -#define DMA_ISR_TCIF (1 << DMA_ISR_TCIF_BIT) -#define DMA_ISR_GIF (1 << DMA_ISR_GIF_BIT) - -#define DMA_ISR_TEIF7_BIT 27 -#define DMA_ISR_HTIF7_BIT 26 -#define DMA_ISR_TCIF7_BIT 25 -#define DMA_ISR_GIF7_BIT 24 -#define DMA_ISR_TEIF6_BIT 23 -#define DMA_ISR_HTIF6_BIT 22 -#define DMA_ISR_TCIF6_BIT 21 -#define DMA_ISR_GIF6_BIT 20 -#define DMA_ISR_TEIF5_BIT 19 -#define DMA_ISR_HTIF5_BIT 18 -#define DMA_ISR_TCIF5_BIT 17 -#define DMA_ISR_GIF5_BIT 16 -#define DMA_ISR_TEIF4_BIT 15 -#define DMA_ISR_HTIF4_BIT 14 -#define DMA_ISR_TCIF4_BIT 13 -#define DMA_ISR_GIF4_BIT 12 -#define DMA_ISR_TEIF3_BIT 11 -#define DMA_ISR_HTIF3_BIT 10 -#define DMA_ISR_TCIF3_BIT 9 -#define DMA_ISR_GIF3_BIT 8 -#define DMA_ISR_TEIF2_BIT 7 -#define DMA_ISR_HTIF2_BIT 6 -#define DMA_ISR_TCIF2_BIT 5 -#define DMA_ISR_GIF2_BIT 4 -#define DMA_ISR_TEIF1_BIT 3 -#define DMA_ISR_HTIF1_BIT 2 -#define DMA_ISR_TCIF1_BIT 1 -#define DMA_ISR_GIF1_BIT 0 - -#define DMA_ISR_TEIF7 (1U << DMA_ISR_TEIF7_BIT) -#define DMA_ISR_HTIF7 (1U << DMA_ISR_HTIF7_BIT) -#define DMA_ISR_TCIF7 (1U << DMA_ISR_TCIF7_BIT) -#define DMA_ISR_GIF7 (1U << DMA_ISR_GIF7_BIT) -#define DMA_ISR_TEIF6 (1U << DMA_ISR_TEIF6_BIT) -#define DMA_ISR_HTIF6 (1U << DMA_ISR_HTIF6_BIT) -#define DMA_ISR_TCIF6 (1U << DMA_ISR_TCIF6_BIT) -#define DMA_ISR_GIF6 (1U << DMA_ISR_GIF6_BIT) -#define DMA_ISR_TEIF5 (1U << DMA_ISR_TEIF5_BIT) -#define DMA_ISR_HTIF5 (1U << DMA_ISR_HTIF5_BIT) -#define DMA_ISR_TCIF5 (1U << DMA_ISR_TCIF5_BIT) -#define DMA_ISR_GIF5 (1U << DMA_ISR_GIF5_BIT) -#define DMA_ISR_TEIF4 (1U << DMA_ISR_TEIF4_BIT) -#define DMA_ISR_HTIF4 (1U << DMA_ISR_HTIF4_BIT) -#define DMA_ISR_TCIF4 (1U << DMA_ISR_TCIF4_BIT) -#define DMA_ISR_GIF4 (1U << DMA_ISR_GIF4_BIT) -#define DMA_ISR_TEIF3 (1U << DMA_ISR_TEIF3_BIT) -#define DMA_ISR_HTIF3 (1U << DMA_ISR_HTIF3_BIT) -#define DMA_ISR_TCIF3 (1U << DMA_ISR_TCIF3_BIT) -#define DMA_ISR_GIF3 (1U << DMA_ISR_GIF3_BIT) -#define DMA_ISR_TEIF2 (1U << DMA_ISR_TEIF2_BIT) -#define DMA_ISR_HTIF2 (1U << DMA_ISR_HTIF2_BIT) -#define DMA_ISR_TCIF2 (1U << DMA_ISR_TCIF2_BIT) -#define DMA_ISR_GIF2 (1U << DMA_ISR_GIF2_BIT) -#define DMA_ISR_TEIF1 (1U << DMA_ISR_TEIF1_BIT) -#define DMA_ISR_HTIF1 (1U << DMA_ISR_HTIF1_BIT) -#define DMA_ISR_TCIF1 (1U << DMA_ISR_TCIF1_BIT) -#define DMA_ISR_GIF1 (1U << DMA_ISR_GIF1_BIT) - -/* Interrupt flag clear register */ - -#define DMA_IFCR_CTEIF7_BIT 27 -#define DMA_IFCR_CHTIF7_BIT 26 -#define DMA_IFCR_CTCIF7_BIT 25 -#define DMA_IFCR_CGIF7_BIT 24 -#define DMA_IFCR_CTEIF6_BIT 23 -#define DMA_IFCR_CHTIF6_BIT 22 -#define DMA_IFCR_CTCIF6_BIT 21 -#define DMA_IFCR_CGIF6_BIT 20 -#define DMA_IFCR_CTEIF5_BIT 19 -#define DMA_IFCR_CHTIF5_BIT 18 -#define DMA_IFCR_CTCIF5_BIT 17 -#define DMA_IFCR_CGIF5_BIT 16 -#define DMA_IFCR_CTEIF4_BIT 15 -#define DMA_IFCR_CHTIF4_BIT 14 -#define DMA_IFCR_CTCIF4_BIT 13 -#define DMA_IFCR_CGIF4_BIT 12 -#define DMA_IFCR_CTEIF3_BIT 11 -#define DMA_IFCR_CHTIF3_BIT 10 -#define DMA_IFCR_CTCIF3_BIT 9 -#define DMA_IFCR_CGIF3_BIT 8 -#define DMA_IFCR_CTEIF2_BIT 7 -#define DMA_IFCR_CHTIF2_BIT 6 -#define DMA_IFCR_CTCIF2_BIT 5 -#define DMA_IFCR_CGIF2_BIT 4 -#define DMA_IFCR_CTEIF1_BIT 3 -#define DMA_IFCR_CHTIF1_BIT 2 -#define DMA_IFCR_CTCIF1_BIT 1 -#define DMA_IFCR_CGIF1_BIT 0 - -#define DMA_IFCR_CTEIF7 (1U << DMA_IFCR_CTEIF7_BIT) -#define DMA_IFCR_CHTIF7 (1U << DMA_IFCR_CHTIF7_BIT) -#define DMA_IFCR_CTCIF7 (1U << DMA_IFCR_CTCIF7_BIT) -#define DMA_IFCR_CGIF7 (1U << DMA_IFCR_CGIF7_BIT) -#define DMA_IFCR_CTEIF6 (1U << DMA_IFCR_CTEIF6_BIT) -#define DMA_IFCR_CHTIF6 (1U << DMA_IFCR_CHTIF6_BIT) -#define DMA_IFCR_CTCIF6 (1U << DMA_IFCR_CTCIF6_BIT) -#define DMA_IFCR_CGIF6 (1U << DMA_IFCR_CGIF6_BIT) -#define DMA_IFCR_CTEIF5 (1U << DMA_IFCR_CTEIF5_BIT) -#define DMA_IFCR_CHTIF5 (1U << DMA_IFCR_CHTIF5_BIT) -#define DMA_IFCR_CTCIF5 (1U << DMA_IFCR_CTCIF5_BIT) -#define DMA_IFCR_CGIF5 (1U << DMA_IFCR_CGIF5_BIT) -#define DMA_IFCR_CTEIF4 (1U << DMA_IFCR_CTEIF4_BIT) -#define DMA_IFCR_CHTIF4 (1U << DMA_IFCR_CHTIF4_BIT) -#define DMA_IFCR_CTCIF4 (1U << DMA_IFCR_CTCIF4_BIT) -#define DMA_IFCR_CGIF4 (1U << DMA_IFCR_CGIF4_BIT) -#define DMA_IFCR_CTEIF3 (1U << DMA_IFCR_CTEIF3_BIT) -#define DMA_IFCR_CHTIF3 (1U << DMA_IFCR_CHTIF3_BIT) -#define DMA_IFCR_CTCIF3 (1U << DMA_IFCR_CTCIF3_BIT) -#define DMA_IFCR_CGIF3 (1U << DMA_IFCR_CGIF3_BIT) -#define DMA_IFCR_CTEIF2 (1U << DMA_IFCR_CTEIF2_BIT) -#define DMA_IFCR_CHTIF2 (1U << DMA_IFCR_CHTIF2_BIT) -#define DMA_IFCR_CTCIF2 (1U << DMA_IFCR_CTCIF2_BIT) -#define DMA_IFCR_CGIF2 (1U << DMA_IFCR_CGIF2_BIT) -#define DMA_IFCR_CTEIF1 (1U << DMA_IFCR_CTEIF1_BIT) -#define DMA_IFCR_CHTIF1 (1U << DMA_IFCR_CHTIF1_BIT) -#define DMA_IFCR_CTCIF1 (1U << DMA_IFCR_CTCIF1_BIT) -#define DMA_IFCR_CGIF1 (1U << DMA_IFCR_CGIF1_BIT) - -/* Channel configuration register */ - -#define DMA_CCR_MEM2MEM_BIT 14 -#define DMA_CCR_MINC_BIT 7 -#define DMA_CCR_PINC_BIT 6 -#define DMA_CCR_CIRC_BIT 5 -#define DMA_CCR_DIR_BIT 4 -#define DMA_CCR_TEIE_BIT 3 -#define DMA_CCR_HTIE_BIT 2 -#define DMA_CCR_TCIE_BIT 1 -#define DMA_CCR_EN_BIT 0 - -#define DMA_CCR_MEM2MEM (1U << DMA_CCR_MEM2MEM_BIT) -#define DMA_CCR_PL (0x3 << 12) -#define DMA_CCR_PL_LOW (0x0 << 12) -#define DMA_CCR_PL_MEDIUM (0x1 << 12) -#define DMA_CCR_PL_HIGH (0x2 << 12) -#define DMA_CCR_PL_VERY_HIGH (0x3 << 12) -#define DMA_CCR_MSIZE (0x3 << 10) -#define DMA_CCR_MSIZE_8BITS (0x0 << 10) -#define DMA_CCR_MSIZE_16BITS (0x1 << 10) -#define DMA_CCR_MSIZE_32BITS (0x2 << 10) -#define DMA_CCR_PSIZE (0x3 << 8) -#define DMA_CCR_PSIZE_8BITS (0x0 << 8) -#define DMA_CCR_PSIZE_16BITS (0x1 << 8) -#define DMA_CCR_PSIZE_32BITS (0x2 << 8) -#define DMA_CCR_MINC (1U << DMA_CCR_MINC_BIT) -#define DMA_CCR_PINC (1U << DMA_CCR_PINC_BIT) -#define DMA_CCR_CIRC (1U << DMA_CCR_CIRC_BIT) -#define DMA_CCR_DIR (1U << DMA_CCR_DIR_BIT) -#define DMA_CCR_DIR_FROM_PER (0U << DMA_CCR_DIR_BIT) -#define DMA_CCR_DIR_FROM_MEM (1U << DMA_CCR_DIR_BIT) -#define DMA_CCR_TEIE (1U << DMA_CCR_TEIE_BIT) -#define DMA_CCR_HTIE (1U << DMA_CCR_HTIE_BIT) -#define DMA_CCR_TCIE (1U << DMA_CCR_TCIE_BIT) -#define DMA_CCR_EN (1U << DMA_CCR_EN_BIT) - -/* - * Devices - */ - -extern dma_dev *DMA1; -extern dma_dev *DMA2; - -/* - * Other types needed by, or useful for, . - */ - -/** - * @brief STM32F3 dma_tube. - * On STM32F3, DMA tubes are just channels. - */ -#define dma_tube dma_channel - -/** - * @brief On STM32F3, dma_channel_reg_map is an alias for dma_tube_reg_map. - * This is for backwards compatibility. */ -#define dma_channel_reg_map dma_tube_reg_map - -/** - * @brief STM32F3 configuration flags for dma_tube_config - * @see struct dma_tube_config - */ -typedef enum dma_cfg_flags { - /** - * Source address increment mode - * - * If this flag is set, the source address is incremented (by the - * source size) after each DMA transfer. - */ - DMA_CFG_SRC_INC = 1U << 31, - - /** - * Destination address increment mode - * - * If this flag is set, the destination address is incremented (by - * the destination size) after each DMA transfer. - */ - DMA_CFG_DST_INC = 1U << 30, - - /** - * Circular mode - * - * This mode is not available for memory-to-memory transfers. - */ - DMA_CFG_CIRC = DMA_CCR_CIRC, - - /** Transfer complete interrupt enable */ - DMA_CFG_CMPLT_IE = DMA_CCR_TCIE, - /** Transfer half-complete interrupt enable */ - DMA_CFG_HALF_CMPLT_IE = DMA_CCR_HTIE, - /** Transfer error interrupt enable */ - DMA_CFG_ERR_IE = DMA_CCR_TEIE, -} dma_cfg_flags; - -/** - * @brief STM32F3 DMA request sources. - * - * IMPORTANT: - * - * 1. On STM32F3, each dma_request_src can only be used by a - * particular tube on a particular DMA controller. For example, - * DMA_REQ_SRC_ADC1 belongs to DMA1, tube 1. DMA2 cannot serve - * requests from ADC1, nor can DMA1 tube 2, etc. If you try to use a - * request source with the wrong DMA controller or tube on STM32F3, - * dma_tube_cfg() will fail. - * - * 2. In general, a DMA tube can only serve a single request source at - * a time, and on STM32F3, Terrible Super-Bad Things will happen if - * two request sources are active for a single tube. - * - * To make all this easier to sort out, these dma_request_src - * enumerators are grouped by DMA controller and tube. - * - * @see struct dma_tube_config - * @see dma_tube_cfg() - */ -typedef enum dma_request_src { - /* Each request source encodes the DMA controller and channel it - * belongs to, for error checking in dma_tube_cfg(). */ - - /* DMA1 request sources */ - - /**@{*/ - /** (DMA1, tube 1) */ - DMA_REQ_SRC_ADC1 = (RCC_DMA1 << 3) | 1, - DMA_REQ_SRC_TIM2_CH3 = (RCC_DMA1 << 3) | 1, - DMA_REQ_SRC_TIM4_CH1 = (RCC_DMA1 << 3) | 1, - DMA_REQ_SRC_TIM17_CH1 = (RCC_DMA1 << 3) | 1, - DMA_REQ_SRC_TIM17_UP = (RCC_DMA1 << 3) | 1, - /**@}*/ - - /**@{*/ - /** (DMA1, tube 2)*/ - DMA_REQ_SRC_SPI1_RX = (RCC_DMA1 << 3) | 2, - DMA_REQ_SRC_USART3_TX = (RCC_DMA1 << 3) | 2, - DMA_REQ_SRC_TIM1_CH1 = (RCC_DMA1 << 3) | 2, - DMA_REQ_SRC_TIM2_UP = (RCC_DMA1 << 3) | 2, - DMA_REQ_SRC_TIM3_CH3 = (RCC_DMA1 << 3) | 2, - /**@}*/ - - /**@{*/ - /** (DMA1, tube 3)*/ - DMA_REQ_SRC_SPI1_TX = (RCC_DMA1 << 3) | 3, - DMA_REQ_SRC_USART3_RX = (RCC_DMA1 << 3) | 3, - DMA_REQ_SRC_TIM1_CH2 = (RCC_DMA1 << 3) | 3, - DMA_REQ_SRC_TIM3_CH4 = (RCC_DMA1 << 3) | 3, - DMA_REQ_SRC_TIM3_UP = (RCC_DMA1 << 3) | 3, - /*DMA_REQ_SRC_TIM6_UP = (RCC_DMA1 << 3) | 3,*/ /* remap in SYSCFGR */ - /*DMA_REQ_SRC_DAC_CH1 = (RCC_DMA1 << 3) | 3,*/ /* remap in SYSCFGR */ - DMA_REQ_SRC_TIM16_CH1 = (RCC_DMA1 << 3) | 3, - DMA_REQ_SRC_TIM16_UP = (RCC_DMA1 << 3) | 3, - /**@}*/ - - /**@{*/ - /** (DMA1, tube 4)*/ - DMA_REQ_SRC_SPI2_RX = (RCC_DMA1 << 3) | 4, - DMA_REQ_SRC_USART1_TX = (RCC_DMA1 << 3) | 4, - DMA_REQ_SRC_I2C2_TX = (RCC_DMA1 << 3) | 4, - DMA_REQ_SRC_TIM1_CH4 = (RCC_DMA1 << 3) | 4, - DMA_REQ_SRC_TIM1_TRIG = (RCC_DMA1 << 3) | 4, - DMA_REQ_SRC_TIM1_COM = (RCC_DMA1 << 3) | 4, - DMA_REQ_SRC_TIM4_CH2 = (RCC_DMA1 << 3) | 4, - /*DMA_REQ_SRC_TIM7_UP = (RCC_DMA1 << 3) | 4,*/ /* remap in SYSCFGR */ - /*DMA_REQ_SRC_DAC_CH2 = (RCC_DMA1 << 3) | 4,*/ /* remap in SYSCFGR */ - /**@}*/ - - /**@{*/ - /** (DMA1, tube 5)*/ - DMA_REQ_SRC_SPI2_TX = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_USART1_RX = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_I2C2_RX = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM1_UP = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM2_CH1 = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM4_CH3 = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM15_CH1 = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM15_UP = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM15_TRIG = (RCC_DMA1 << 3) | 5, - DMA_REQ_SRC_TIM15_COM = (RCC_DMA1 << 3) | 5, - /**@}*/ - - /**@{*/ - /** (DMA1, tube 6)*/ - DMA_REQ_SRC_USART2_RX = (RCC_DMA1 << 3) | 6, - DMA_REQ_SRC_I2C1_TX = (RCC_DMA1 << 3) | 6, - DMA_REQ_SRC_TIM1_CH3 = (RCC_DMA1 << 3) | 6, - DMA_REQ_SRC_TIM3_CH1 = (RCC_DMA1 << 3) | 6, - DMA_REQ_SRC_TIM3_TRIG = (RCC_DMA1 << 3) | 6, - /*DMA_REQ_SRC_TIM16_CH1 = (RCC_DMA1 << 3) | 6,*/ /* remap in SYSCFGR */ - /*DMA_REQ_SRC_TIM16_UP = (RCC_DMA1 << 3) | 6,*/ /* remap in SYSCFGR */ - /**@}*/ - - /**@{*/ - /* Tube 7 */ - DMA_REQ_SRC_USART2_TX = (RCC_DMA1 << 3) | 7, - DMA_REQ_SRC_I2C1_RX = (RCC_DMA1 << 3) | 7, - DMA_REQ_SRC_TIM2_CH2 = (RCC_DMA1 << 3) | 7, - DMA_REQ_SRC_TIM2_CH4 = (RCC_DMA1 << 3) | 7, - DMA_REQ_SRC_TIM4_UP = (RCC_DMA1 << 3) | 7, - /**@}*/ - - /* DMA2 request sources */ - - /**@{*/ - /** (DMA2, tube 1)*/ - DMA_REQ_SRC_ADC2 = (RCC_DMA2 << 3) | 1, - DMA_REQ_SRC_SPI3_RX = (RCC_DMA2 << 3) | 1, - DMA_REQ_SRC_TIM8_CH3 = (RCC_DMA2 << 3) | 1, - DMA_REQ_SRC_TIM8_UP = (RCC_DMA2 << 3) | 1, - /**@}*/ - - /**@{*/ - /** (DMA2, tube 2)*/ - DMA_REQ_SRC_ADC4 = (RCC_DMA2 << 3) | 2, - DMA_REQ_SRC_SPI3_TX = (RCC_DMA2 << 3) | 2, - DMA_REQ_SRC_TIM8_CH4 = (RCC_DMA2 << 3) | 2, - DMA_REQ_SRC_TIM8_TRIG = (RCC_DMA2 << 3) | 2, - DMA_REQ_SRC_TIM8_COM = (RCC_DMA2 << 3) | 2, - /**@}*/ - - /**@{*/ - /** (DMA2, tube 3)*/ - /* DMA_REQ_SRC_ADC2 = (RCC_DMA2 << 3) | 3,*/ /* remap in SYSCFGR */ - DMA_REQ_SRC_UART4_RX = (RCC_DMA2 << 3) | 3, - DMA_REQ_SRC_TIM6_UP = (RCC_DMA2 << 3) | 3, - DMA_REQ_SRC_DAC1_CH1 = (RCC_DMA2 << 3) | 3, - DMA_REQ_SRC_TIM8_CH1 = (RCC_DMA2 << 3) | 3, - /**@}*/ - - /**@{*/ - /** (DMA2, tube 4)*/ - /*DMA_REQ_SRC_ADC4 = (RCC_DMA2 << 3) | 4,*/ /* remap in SYSCFGR */ - DMA_REQ_SRC_TIM7_UP = (RCC_DMA2 << 3) | 4, - DMA_REQ_SRC_DAC1_CH2 = (RCC_DMA2 << 3) | 4, - /**@}*/ - - /**@{*/ - /** (DMA2, tube 5)*/ - DMA_REQ_SRC_ADC3 = (RCC_DMA2 << 3) | 5, - DMA_REQ_SRC_UART4_TX = (RCC_DMA2 << 3) | 5, - DMA_REQ_SRC_TIM8_CH2 = (RCC_DMA2 << 3) | 5, - /**@}*/ -} dma_request_src; - -/* - * Convenience routines. - */ - -/** - * @brief On STM32F3, dma_is_channel_enabled() is an alias for - * dma_is_enabled(). - * This is for backwards compatibility. - */ -#define dma_is_channel_enabled dma_is_enabled - -#define DMA_CHANNEL_NREGS 5 /* accounts for reserved word */ -static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, dma_tube tube) { - __io uint32 *ccr1 = &dev->regs->CCR1; - return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (tube - 1)); -} - -/** - * @brief On STM32F3, dma_channel_regs() is an alias for dma_tube_regs(). - * This is for backwards compatibility. */ -#define dma_channel_regs(dev, ch) dma_tube_regs(dev, ch) - -static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube) { - return (uint8)(dma_tube_regs(dev, tube)->CCR & DMA_CCR_EN); -} - -static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube) { - uint8 shift = (tube - 1) * 4; - return (dev->regs->ISR >> shift) & 0xF; -} - -static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) { - dev->regs->IFCR = (1U << (4 * (tube - 1))); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/exti.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/exti.h deleted file mode 100644 index 05ed1e6..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/exti.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/exti.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 external interrupts - */ - -#ifndef _LIBMAPLE_STM32F3_EXTI_H_ -#define _LIBMAPLE_STM32F3_EXTI_H_ - -#ifdef __cpluspus -extern "C" { -#endif - -//FIXME F3 has up to 36 EXTIs, expose and handle internal EXTIs 16-35 -struct exti_reg_map; -#define EXTI_BASE ((struct exti_reg_map*)0x40010400) - -#ifdef __cpluspus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/flash.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/flash.h deleted file mode 100644 index 85baf9b..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/flash.h +++ /dev/null @@ -1,164 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/flash.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Flash header. - * - * Provides register map, base pointer, and register bit definitions - * for the Flash controller on the STM32F3 line, along with - * series-specific configuration values. - */ - -#ifndef _LIBMAPLE_STM32F3_FLASH_H_ -#define _LIBMAPLE_STM32F3_FLASH_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Register map - */ - -/** @brief STM32F3 Flash register map type */ -typedef struct flash_reg_map { - __io uint32 ACR; /**< Access control register */ - __io uint32 KEYR; /**< Key register */ - __io uint32 OPTKEYR; /**< OPTKEY register */ - __io uint32 SR; /**< Status register */ - __io uint32 CR; /**< Control register */ - __io uint32 AR; /**< Address register */ - __io uint32 OBR; /**< Option byte register */ - __io uint32 WRPR; /**< Write protection register */ -} flash_reg_map; - -#define FLASH_BASE ((struct flash_reg_map*)0x40022000) - -/* - * Register bit definitions - */ - -/* Access control register */ - -#define FLASH_ACR_PRFTBS_BIT 5 -#define FLASH_ACR_PRFTBE_BIT 4 -#define FLASH_ACR_HLFCYA_BIT 3 - -#define FLASH_ACR_PRFTBS (1U << FLASH_ACR_PRFTBS_BIT) -#define FLASH_ACR_PRFTBE (1U << FLASH_ACR_PRFTBE_BIT) -#define FLASH_ACR_HLFCYA (1U << FLASH_ACR_HLFCYA_BIT) -#define FLASH_ACR_LATENCY 0x7 - -/* Status register */ - -#define FLASH_SR_EOP_BIT 5 -#define FLASH_SR_WRPRTERR_BIT 4 -#define FLASH_SR_PGERR_BIT 2 -#define FLASH_SR_BSY_BIT 0 - -#define FLASH_SR_EOP (1U << FLASH_SR_EOP_BIT) -#define FLASH_SR_WRPRTERR (1U << FLASH_SR_WRPRTERR_BIT) -#define FLASH_SR_PGERR (1U << FLASH_SR_PGERR_BIT) -#define FLASH_SR_BSY (1U << FLASH_SR_BSY_BIT) - -/* Control register */ - -#define FLASH_CR_OBL_LAUNCH_BIT 13 -#define FLASH_CR_EOPIE_BIT 12 -#define FLASH_CR_ERRIE_BIT 10 -#define FLASH_CR_OPTWRE_BIT 9 -#define FLASH_CR_LOCK_BIT 7 -#define FLASH_CR_STRT_BIT 6 -#define FLASH_CR_OPTER_BIT 5 -#define FLASH_CR_OPTPG_BIT 4 -#define FLASH_CR_MER_BIT 2 -#define FLASH_CR_PER_BIT 1 -#define FLASH_CR_PG_BIT 0 - -#define FLASH_CR_OBL_LAUNCH (1U << FLASH_CR_OBL_LAUNCH_BIT) -#define FLASH_CR_EOPIE (1U << FLASH_CR_EOPIE_BIT) -#define FLASH_CR_ERRIE (1U << FLASH_CR_ERRIE_BIT) -#define FLASH_CR_OPTWRE (1U << FLASH_CR_OPTWRE_BIT) -#define FLASH_CR_LOCK (1U << FLASH_CR_LOCK_BIT) -#define FLASH_CR_STRT (1U << FLASH_CR_STRT_BIT) -#define FLASH_CR_OPTER (1U << FLASH_CR_OPTER_BIT) -#define FLASH_CR_OPTPG (1U << FLASH_CR_OPTPG_BIT) -#define FLASH_CR_MER (1U << FLASH_CR_MER_BIT) -#define FLASH_CR_PER (1U << FLASH_CR_PER_BIT) -#define FLASH_CR_PG (1U << FLASH_CR_PG_BIT) - -/* Option byte register */ - -#define FLASH_OBR_DATA1_SHIFT 24 -#define FLASH_OBR_DATA0_SHIFT 16 -#define FLASH_OBR_BYTE_SHIFT 8 -#define FLASH_OBR_SRAM_PE_BIT 14 -#define FLASH_OBR_VDDA_MONITOR_BIT 13 -#define FLASH_OBR_nBOOT1_BIT 12 -#define FLASH_OBR_nRST_STDBY_BIT 10 -#define FLASH_OBR_nRST_STOP_BIT 9 -#define FLASH_OBR_WDG_SW_BIT 8 -#define FLASH_OBR_RDPRT_SHIFT 1 -#define FLASH_OBR_OPTERR_BIT 0 - -#define FLASH_OBR_DATA1 (0xFF << FLASH_OBR_DATA1_SHIFT) -#define FLASH_OBR_DATA0 (0xFF << FLASH_OBR_DATA0_SHIFT) -#define FLASH_OBR_BYTE (0xFF << FLASH_OBR_BYTE_SHIFT) -#define FLASH_OBR_SRAM_PE_STDBY (1U << FLASH_OBR_SRAM_PE_STDBY_BIT) -#define FLASH_OBR_VDDA_MONITOR_STDBY (1U << FLASH_OBR_VDDA_MONITOR_STDBY_BIT) -#define FLASH_OBR_nBOOT1_STDBY (1U << FLASH_OBR_nBOOT1_STDBY_BIT) -#define FLASH_OBR_nRST_STDBY (1U << FLASH_OBR_nRST_STDBY_BIT) -#define FLASH_OBR_nRST_STOP (1U << FLASH_OBR_nRST_STOP_BIT) -#define FLASH_OBR_WDG_SW (1U << FLASH_OBR_WDG_SW_BIT) -#define FLASH_OBR_RDPRT (0x3 << FLASH_OBR_RDPRT_SHIFT) -#define FLASH_OBR_OPTERR (1U << FLASH_OBR_OPTERR_BIT) - -/* - * Series-specific configuration values. - */ - -#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_2 - -/* Flash memory features available via ACR */ -enum { - FLASH_PREFETCH = 0x10, - FLASH_HALF_CYCLE = 0x8, - FLASH_ICACHE = 0x0, /* Not available on STM32F3 */ - FLASH_DCACHE = 0x0, /* Not available on STM32F3 */ -}; - -/* TODO add routines for option byte handling, e.g. nBoot1 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/fpu.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/fpu.h deleted file mode 100644 index dc5d4ab..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/fpu.h +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/fpu.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Floating Point Unit support. - */ - -#ifndef _LIBMAPLE_STM32F3_FPU_H_ -#define _LIBMAPLE_STM32F3_FPU_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -/* - * FPU register maps and devices - */ - -/** FPU register map type */ -typedef struct fpu_reg_map { - __io uint32 CPACR; /**< coprocessor access control register */ - __io uint32 FPCCR; /**< floating-point context control register */ - __io uint32 FPCAR; /**< floating-point context address register */ - __io uint32 FPDSCR; /**< floating-point default status control register */ -} fpu_reg_map; - -#define FPU_BASE ((struct fpu_reg_map*)(SCB_BASE + 0x88)) - -/* TODO - * give registry bitfields here - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/gpio.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/gpio.h deleted file mode 100644 index 50e8c09..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/gpio.h +++ /dev/null @@ -1,255 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/gpio.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 GPIO support. - */ - -#ifndef _LIBMAPLE_STM32F3_GPIO_H_ -#define _LIBMAPLE_STM32F3_GPIO_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * GPIO register maps and devices - */ - -/** GPIO register map type */ -typedef struct gpio_reg_map { - __io uint32 MODER; /**< Mode register */ - __io uint32 OTYPER; /**< Output type register */ - __io uint32 OSPEEDR; /**< Output speed register */ - __io uint32 PUPDR; /**< Pull-up/pull-down register */ - __io uint32 IDR; /**< Input data register */ - __io uint32 ODR; /**< Output data register */ - __io uint32 BSRR; /**< Bit set/reset register */ - __io uint32 LCKR; /**< Configuration lock register */ - __io uint32 AFRL; /**< Alternate function low register */ - __io uint32 AFRH; /**< Alternate function high register */ - __io uint32 BRR; /**< Port bit reset register */ -} gpio_reg_map; - -/** GPIO port A register map base pointer */ -#define GPIOA_BASE ((struct gpio_reg_map*)0x48000000) -/** GPIO port B register map base pointer */ -#define GPIOB_BASE ((struct gpio_reg_map*)0x48000400) -/** GPIO port C register map base pointer */ -#define GPIOC_BASE ((struct gpio_reg_map*)0x48000800) -/** GPIO port D register map base pointer */ -#define GPIOD_BASE ((struct gpio_reg_map*)0x48000C00) -/** GPIO port E register map base pointer */ -#define GPIOE_BASE ((struct gpio_reg_map*)0x48001000) -/** GPIO port F register map base pointer */ -#define GPIOF_BASE ((struct gpio_reg_map*)0x48001400) - -struct gpio_dev; -extern struct gpio_dev* const GPIOA; -extern struct gpio_dev gpioa; -extern struct gpio_dev* const GPIOB; -extern struct gpio_dev gpiob; -extern struct gpio_dev* const GPIOC; -extern struct gpio_dev gpioc; -extern struct gpio_dev* const GPIOD; -extern struct gpio_dev gpiod; -extern struct gpio_dev* const GPIOE; -extern struct gpio_dev gpioe; -extern struct gpio_dev* const GPIOF; -extern struct gpio_dev gpiof; - -/* - * Register bit definitions - * - * Currently, we only provide masks to be used for shifting for some - * registers, rather than repeating the same values 16 times. - */ - -/* Mode register */ - -#define GPIO_MODER_INPUT 0x0 -#define GPIO_MODER_OUTPUT 0x1 -#define GPIO_MODER_AF 0x2 -#define GPIO_MODER_ANALOG 0x3 - -/* Output type register */ - -#define GPIO_OTYPER_PP 0x0 -#define GPIO_OTYPER_OD 0x1 - -/* Output speed register */ - -#define GPIO_OSPEEDR_LOW 0x0 -#define GPIO_OSPEEDR_MED 0x1 -#define GPIO_OSPEEDR_FAST 0x2 -#define GPIO_OSPEEDR_HIGH 0x3 - -/* Pull-up/pull-down register */ - -#define GPIO_PUPDR_NOPUPD 0x0 -#define GPIO_PUPDR_PU 0x1 -#define GPIO_PUPDR_PD 0x2 - -/* Alternate function register low */ - -#define GPIO_AFRL_AF0 (0xFU << 0) -#define GPIO_AFRL_AF1 (0xFU << 4) -#define GPIO_AFRL_AF2 (0xFU << 8) -#define GPIO_AFRL_AF3 (0xFU << 12) -#define GPIO_AFRL_AF4 (0xFU << 16) -#define GPIO_AFRL_AF5 (0xFU << 20) -#define GPIO_AFRL_AF6 (0xFU << 24) -#define GPIO_AFRL_AF7 (0xFU << 28) - -/* Alternate function register high */ - -#define GPIO_AFRH_AF8 (0xFU << 0) -#define GPIO_AFRH_AF9 (0xFU << 4) -#define GPIO_AFRH_AF10 (0xFU << 8) -#define GPIO_AFRH_AF11 (0xFU << 12) -#define GPIO_AFRH_AF12 (0xFU << 16) -#define GPIO_AFRH_AF13 (0xFU << 20) -#define GPIO_AFRH_AF14 (0xFU << 24) -#define GPIO_AFRH_AF15 (0xFU << 28) - -/* - * GPIO routines - */ - -/** - * @brief GPIO pin modes - */ -typedef enum gpio_pin_mode { - GPIO_MODE_INPUT = GPIO_MODER_INPUT, /**< Input mode */ - GPIO_MODE_OUTPUT = GPIO_MODER_OUTPUT, /**< Output mode */ - GPIO_MODE_AF = GPIO_MODER_AF, /**< Alternate function mode */ - GPIO_MODE_ANALOG = GPIO_MODER_ANALOG, /**< Analog mode */ -} gpio_pin_mode; - -/** - * @brief Additional flags to be used when setting a pin's mode. - * - * Beyond the basic modes (input, general purpose output, alternate - * function, and analog), there are three parameters that can affect a - * pin's mode: - * - * 1. Output type: push/pull or open-drain. This only has an effect - * for output modes. Choices are: GPIO_MODEF_TYPE_PP (the default) - * and GPIO_MODEF_TYPE_OD. - * - * 2. Output speed: specifies the frequency at which a pin changes - * state. This only has an effect for output modes. Choices are: - * GPIO_MODEF_SPEED_LOW (default), GPIO_MODEF_SPEED_MED, - * GPIO_MODEF_SPEED_FAST, and GPIO_MODEF_SPEED_HIGH. - * - * 3. Push/pull setting: All GPIO pins have weak pull-up and pull-down - * resistors that can be enabled when the pin's mode is - * set. Choices are: GPIO_MODEF_PUPD_NONE (default), - * GPIO_MODEF_PUPD_PU, and GPIO_MODEF_PUPD_PD. - */ -typedef enum gpio_mode_flags { - /* Output type in bit 0 */ - GPIO_MODEF_TYPE_PP = GPIO_OTYPER_PP, /**< Output push/pull (default). - Applies only when the mode - specifies output. */ - GPIO_MODEF_TYPE_OD = GPIO_OTYPER_OD, /**< Output open drain. - Applies only when the mode - specifies output. */ - - /* Speed in bits 2:1 */ - GPIO_MODEF_SPEED_LOW = GPIO_OSPEEDR_LOW << 1, /**< Low speed (default): - 2 MHz. */ - GPIO_MODEF_SPEED_MED = GPIO_OSPEEDR_MED << 1, /**< Medium speed: 25 MHz. */ - GPIO_MODEF_SPEED_FAST = GPIO_OSPEEDR_FAST << 1, /**< Fast speed: 50 MHz. */ - GPIO_MODEF_SPEED_HIGH = GPIO_OSPEEDR_HIGH << 1, /**< High speed: FIXME one of those does not exist on the F3 - 100 MHz on 30 pF, - 80 MHz on 15 pF. */ - - /* Pull-up/pull-down in bits 4:3 */ - GPIO_MODEF_PUPD_NONE = GPIO_PUPDR_NOPUPD << 3, /**< No pull-up/pull-down - (default). */ - GPIO_MODEF_PUPD_PU = GPIO_PUPDR_PU << 3, /**< Pull-up */ - GPIO_MODEF_PUPD_PD = GPIO_PUPDR_PD << 3, /**< Pull-down */ -} gpio_mode_flags; - -void gpio_set_modef(struct gpio_dev *dev, - uint8 bit, - gpio_pin_mode mode, - unsigned flags); - -/** - * @brief Set the mode of a GPIO pin. - * - * Calling this function is equivalent to calling gpio_set_modef(dev, - * pin, mode, GPIO_MODE_SPEED_HIGH). Note that this overrides the - * default speed. - * - * @param dev GPIO device. - * @param bit Bit on the device whose mode to set, 0--15. - * @param mode Mode to set the pin to. - */ -static inline void gpio_set_mode(struct gpio_dev *dev, - uint8 bit, - gpio_pin_mode mode) { - gpio_set_modef(dev, bit, mode, GPIO_MODEF_SPEED_HIGH); -} - -/** - * @brief GPIO alternate functions. - * Use these to select an alternate function for a pin. - * @see gpio_set_af() - */ -typedef enum gpio_af { - GPIO_AF_0 = 0x0, /**< alternate function 0. */ - GPIO_AF_1 = 0x1, /**< alternate function 1. */ - GPIO_AF_2 = 0x2, /**< alternate function 2. */ - GPIO_AF_3 = 0x3, /**< alternate function 3. */ - GPIO_AF_4 = 0x4, /**< alternate function 4. */ - GPIO_AF_5 = 0x5, /**< alternate function 5. */ - GPIO_AF_6 = 0x6, /**< alternate function 6. */ - GPIO_AF_7 = 0x7, /**< alternate function 7. */ - GPIO_AF_8 = 0x8, /**< alternate function 8. */ - GPIO_AF_9 = 0x9, /**< alternate function 9. */ - GPIO_AF_10 = 0xA, /**< alternate function 10. */ - GPIO_AF_11 = 0xB, /**< alternate function 11. */ - GPIO_AF_12 = 0xC, /**< alternate function 12. */ - GPIO_AF_13 = 0xD, /**< alternate function 13. */ - GPIO_AF_14 = 0xE, /**< alternate function 14. */ - GPIO_AF_15 = 0xF, /**< alternate function 14. */ -} gpio_af; - -void gpio_set_af(struct gpio_dev *dev, uint8 bit, gpio_af af); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/i2c.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/i2c.h deleted file mode 100644 index c7be377..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/i2c.h +++ /dev/null @@ -1,315 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/i2c.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 I2C - */ - -#ifndef _LIBMAPLE_STM32F3_I2C_H_ -#define _LIBMAPLE_STM32F3_I2C_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include -#include - -/* - * Register maps - */ - -/** I2C register map type */ -typedef struct i2c_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 OAR1; /**< Own address register 1 */ - __io uint32 OAR2; /**< Own address register 2 */ - __io uint32 TIMINGR; /**< Timing register */ - __io uint32 TIMEOUTR; /**< Timeout register */ - __io uint32 ISR; /**< Interrupt and status register */ - __io uint32 ICR; /**< Interrupt clear register */ - __io uint32 PECR; /**< PEC register */ - __io uint32 RXDR; /**< Receive data register */ - __io uint32 TXDR; /**< Transmit data register */ -} i2c_reg_map; - -extern i2c_dev* const I2C1; -extern i2c_dev* const I2C2; - -/* - * Register map base pointers - */ - -/** STM32F3 I2C1 register map base pointer */ -#define I2C1_BASE ((struct i2c_reg_map*)0x40005400) -/** STM32F3 I2C2 register map base pointer */ -#define I2C2_BASE ((struct i2c_reg_map*)0x40005800) - -/* - * Register bit definitions - */ - -/* Control register 1 */ -#define I2C_CR1_PECEN_BIT 23 -#define I2C_CR1_ALERTEN_BIT 22 -#define I2C_CR1_SMBDEN_BIT 21 -#define I2C_CR1_SMBHEN_BIT 20 -#define I2C_CR1_GCEN_BIT 19 -#define I2C_CR1_WUPEN_BIT 18 -#define I2C_CR1_NOSTRETCH_BIT 17 -#define I2C_CR1_SBC_BIT 16 -#define I2C_CR1_RXDMAEN_BIT 15 -#define I2C_CR1_TXDMAEN_BIT 14 -#define I2C_CR1_ANFOFF_BIT 12 -#define I2C_CR1_DNF_SHIFT 8 -#define I2C_CR1_ERRIE_BIT 7 -#define I2C_CR1_TCIE_BIT 6 -#define I2C_CR1_STOPIE_BIT 5 -#define I2C_CR1_NACKIE_BIT 4 -#define I2C_CR1_ADDRIE_BIT 3 -#define I2C_CR1_RXIE_BIT 2 -#define I2C_CR1_TXIE_BIT 1 -#define I2C_CR1_PE_BIT 0 - -#define I2C_CR1_PECEN (1U << I2C_CR1_PECEN_BIT) -#define I2C_CR1_ALERTEN (1U << I2C_CR1_ALERTEN_BIT) -#define I2C_CR1_SMBDEN (1U << I2C_CR1_SMBDEN_BIT) -#define I2C_CR1_SMBHEN (1U << I2C_CR1_SMBHEN_BIT) -#define I2C_CR1_GCEN (1U << I2C_CR1_GCEN_BIT) -#define I2C_CR1_WUPEN (1U << I2C_CR1_WUPEN_BIT) -#define I2C_CR1_NOSTRETCH (1U << I2C_CR1_NOSTRETCH_BIT) -#define I2C_CR1_SBC (1U << I2C_CR1_SBC_BIT) -#define I2C_CR1_RXDMAEN (1U << I2C_CR1_RXDMAEN_BIT) -#define I2C_CR1_TXDMAEN (1U << I2C_CR1_TXDMAEN_BIT) -#define I2C_CR1_ANFOFF (1U << I2C_CR1_ANFOFF_BIT) -#define I2C_CR1_DNF (0xF << I2C_CR1_DNF_SHIFT) -#define I2C_CR1_ERRIE (1U << I2C_CR1_ERRIE_BIT) -#define I2C_CR1_TCIE (1U << I2C_CR1_TCIE_BIT) -#define I2C_CR1_STOPIE (1U << I2C_CR1_STOPIE_BIT) -#define I2C_CR1_NACKIE (1U << I2C_CR1_NACKIE_BIT) -#define I2C_CR1_ADDRIE (1U << I2C_CR1_ADDRIE_BIT) -#define I2C_CR1_RXIE (1U << I2C_CR1_RXIE_BIT) -#define I2C_CR1_TXIE (1U << I2C_CR1_TXIE_BIT) -#define I2C_CR1_PE (1U << I2C_CR1_PE_BIT) - -/* Control register 2 */ -#define I2C_CR2_PECBYTE_BIT 26 -#define I2C_CR2_AUTOEND_BIT 25 -#define I2C_CR2_RELOAD_BIT 24 -#define I2C_CR2_NBYTES_SHIFT 16 -#define I2C_CR2_NACK_BIT 15 -#define I2C_CR2_STOP_BIT 14 -#define I2C_CR2_START_BIT 13 -#define I2C_CR2_HEAD10R_BIT 12 -#define I2C_CR2_ADD10_BIT 11 -#define I2C_CR2_RD_WRN_BIT 10 -#define I2C_CR2_SADD_7_BIT_SHIFT 1 -#define I2C_CR2_SADD_10_BIT_SHIFT 0 - -#define I2C_CR2_PECBYTE (1U << I2C_CR2_PECBYTE_BIT) -#define I2C_CR2_AUTOEND (1U << I2C_CR2_AUTOEND_BIT) -#define I2C_CR2_RELOAD (1U << I2C_CR2_RELOAD_BIT) -#define I2C_CR2_NBYTES (0xFF << I2C_CR2_NBYTES_SHIFT) -#define I2C_CR2_NACK (1U << I2C_CR2_NACK_BIT) -#define I2C_CR2_STOP (1U << I2C_CR2_STOP_BIT) -#define I2C_CR2_START (1U << I2C_CR2_START_BIT) -#define I2C_CR2_HEAD10R (1U << I2C_CR2_HEAD10R_BIT) -#define I2C_CR2_ADD10 (1U << I2C_CR2_ADD10_BIT) -#define I2C_CR2_RD_WRN (1U << I2C_CR2_RD_WRN_BIT) -#define I2C_CR2_SADD_7_BIT (0x7F << I2C_CR2_SADD_7_BIT_SHIFT) -#define I2C_CR2_SADD_10_BIT (0x3FF << I2C_CR2_SADD_10_BIT_SHIFT) - -/* Own address register 1 */ -#define I2C_OAR1_OA1EN_BIT 15 -#define I2C_OAR1_OA1MODE_BIT 10 -#define I2C_OAR1_OA1_7_BIT_SHIFT 1 -#define I2C_OAR1_OA1_10_BIT_SHIFT 0 - -#define I2C_OAR1_OA1EN (1U << I2C_OAR1_OA1EN_BIT) -#define I2C_OAR1_OA1MODE (1U << I2C_OAR1_OA1MODE_BIT) -#define I2C_OAR1_OA1_7_BIT (0x7F << I2C_OAR1_OA1_7_BIT_SHIFT) -#define I2C_OAR1_OA1_10_BIT (0x3FF << I2C_OAR1_OA1_10_BIT_SHIFT) - -/* Own address register 2 */ -#define I2C_OAR2_OA2EN_BIT 15 -#define I2C_OAR2_OA2MSK_SHIFT 8 -#define I2C_OAR2_OA2_7_BIT_SHIFT 1 - -#define I2C_OAR2_OA2EN (1U << I2C_OAR2_OA2EN_BIT) -#define I2C_OAR2_OA2MSK (0x7 << I2C_OAR2_OA2MSK_SHIFT) -#define I2C_OAR2_OA2_7_BIT (0x7F << I2C_OAR2_OA2_7_BIT_SHIFT) - -/* Timing register */ -#define I2C_TIMINGR_PRESC_SHIFT 28 -#define I2C_TIMINGR_SCLDEL_SHIFT 20 -#define I2C_TIMINGR_SDADEL_SHIFT 16 -#define I2C_TIMINGR_SCLH_SHIFT 8 -#define I2C_TIMINGR_SCLL_SHIFT 0 - -#define I2C_TIMINGR_PRESC (0xF << I2C_TIMINGR_PRESC_SHIFT) -#define I2C_TIMINGR_SCLDEL (0xF << I2C_TIMINGR_SCLDEL_SHIFT) -#define I2C_TIMINGR_SCADEL (0xF << I2C_TIMINGR_SCADEL_SHIFT) -#define I2C_TIMINGR_SCLH (0xFF << I2C_TIMINGR_SCLH_SHIFT) -#define I2C_TIMINGR_SCLL (0xFF << I2C_TIMINGR_SCLL_SHIFT) - -/* Timeout register */ -#define I2C_TIMEOUTR_TEXTEN_BIT 31 -#define I2C_TIMEOUTR_TIMEOUTB_SHIFT 16 -#define I2C_TIMEOUTR_TIMOUTEN_BIT 15 -#define I2C_TIMEOUTR_TIDLE_BIT 12 -#define I2C_TIMEOUTR_TIMEOUTA_SHIFT 0 - -#define I2C_TIMEOUTR_TEXTEN (1U << I2C_TIMEOUTR_TEXTEN_BIT) -#define I2C_TIMEOUTR_TIMEOUTB (0xFFF << I2C_TIMEOUTR_TIMEOUTB_SHIFT) -#define I2C_TIMEOUTR_TIMOUTEN (1U << I2C_TIMEOUTR_TIMOUTEN_BIT) -#define I2C_TIMEOUTR_TIDLE (1U << I2C_TIMEOUTR_TIDLE_BIT) -#define I2C_TIMEOUTR_TIMEOUTA (0xFFF << I2C_TIMEOUTR_TIMEOUTA_SHIFT) - -/* Interrupt and status register */ -#define I2C_ISR_ADDCODE_SHIFT 17 -#define I2C_ISR_DIR_BIT 16 -#define I2C_ISR_BUSY_BIT 15 -#define I2C_ISR_ALERT_BIT 13 -#define I2C_ISR_TIMEOUT_BIT 12 -#define I2C_ISR_PECERR_BIT 11 -#define I2C_ISR_OVR_BIT 10 -#define I2C_ISR_ARLO_BIT 9 -#define I2C_ISR_BERR_BIT 8 -#define I2C_ISR_TCR_BIT 7 -#define I2C_ISR_TC_BIT 6 -#define I2C_ISR_STOPF_BIT 5 -#define I2C_ISR_NACKF_BIT 4 -#define I2C_ISR_ADDR_BIT 3 -#define I2C_ISR_RXNE_BIT 2 -#define I2C_ISR_TXIS_BIT 1 -#define I2C_ISR_TXE_BIT 0 - -#define I2C_ISR_ADDCODE (0x7F << I2C_ISR_ADDCODE_SHIFT) -#define I2C_ISR_ALERTCF (1U << I2C_ISR_ALERTCF_BIT) -#define I2C_ISR_DIR (1U << I2C_ISR_DIR_BIT) -#define I2C_ISR_BUSY (1U << I2C_ISR_BUSY_BIT) -#define I2C_ISR_ALERT (1U << I2C_ISR_ALERT_BIT) -#define I2C_ISR_TIMEOUT (1U << I2C_ISR_TIMEOUT_BIT) -#define I2C_ISR_PECERR (1U << I2C_ISR_PECERR_BIT) -#define I2C_ISR_OVR (1U << I2C_ISR_OVR_BIT) -#define I2C_ISR_ARLO (1U << I2C_ISR_ARLO_BIT) -#define I2C_ISR_BERR (1U << I2C_ISR_BERR_BIT) -#define I2C_ISR_TCR (1U << I2C_ISR_TCR_BIT) -#define I2C_ISR_TC (1U << I2C_ISR_TC_BIT) -#define I2C_ISR_STOPF (1U << I2C_ISR_STOPF_BIT) -#define I2C_ISR_NACKF (1U << I2C_ISR_NACKF_BIT) -#define I2C_ISR_ADDR (1U << I2C_ISR_ADDR_BIT) -#define I2C_ISR_RXNE (1U << I2C_ISR_RXNE_BIT) -#define I2C_ISR_TXIS (1U << I2C_ISR_TXIS_BIT) -#define I2C_ISR_TXE (1U << I2C_ISR_TXE_BIT) - -/* Interrupt clear register */ -#define I2C_ICR_ALERTCF_BIT 13 -#define I2C_ICR_TIMOUTCF_BIT 12 -#define I2C_ICR_PECCF_BIT 11 -#define I2C_ICR_OVRCF_BIT 10 -#define I2C_ICR_ARLOCF_BIT 9 -#define I2C_ICR_BERRCF_BIT 8 -#define I2C_ICR_STOPCF_BIT 5 -#define I2C_ICR_NACKCF_BIT 4 -#define I2C_ICR_ADDRCF_BIT 3 - -#define I2C_ICR_ALERTCF (1U << I2C_ICR_ALERTCF_BIT) -#define I2C_ICR_TIMOUTCF (1U << I2C_ICR_TIMOUTCF_BIT) -#define I2C_ICR_PECCF (1U << I2C_ICR_PECERRCF_BIT) -#define I2C_ICR_OVRCF (1U << I2C_ICR_OVRCF_BIT) -#define I2C_ICR_ARLOCF (1U << I2C_ICR_ARLOCF_BIT) -#define I2C_ICR_BERRCF (1U << I2C_ICR_BERRCF_BIT) -#define I2C_ICR_STOPCF (1U << I2C_ICR_STOPCF_BIT) -#define I2C_ICR_NACKCF (1U << I2C_ICR_NACKCF_BIT) -#define I2C_ICR_ADDRCF (1U << I2C_ICR_ADDRCF_BIT) - -/* PEC register */ -#define I2C_PEC_PEC 0xFF - -/* Receive data register */ -#define I2C_RXDR_RXDATA 0xFF - -/* Transmit data register */ -#define I2C_TXDR_TXDATA 0xFF - -/* - * Timing configurations - */ - -/* Timing configuration for I2C clock running at 8MHz */ - -/* NOTE: - * I2C is clocked by HSI (8MHz) by default - * if clock source is changed with RCC_CFGR_I2C1SW/I2C2SW, - * these values have to be adapted - */ -typedef enum i2c_timing { - I2C_TIMING_10_kHz = (0x01 << I2C_TIMINGR_PRESC_SHIFT) - + (0x04 << I2C_TIMINGR_SCLDEL_SHIFT) - + (0x02 << I2C_TIMINGR_SDADEL_SHIFT) - + (0xC3 << I2C_TIMINGR_SCLH_SHIFT) - + (0xC7 << I2C_TIMINGR_SCLL_SHIFT), - - I2C_TIMING_100_kHz = (0x01 << I2C_TIMINGR_PRESC_SHIFT) - + (0x04 << I2C_TIMINGR_SCLDEL_SHIFT) - + (0x02 << I2C_TIMINGR_SDADEL_SHIFT) - + (0x0F << I2C_TIMINGR_SCLH_SHIFT) - + (0x13 << I2C_TIMINGR_SCLL_SHIFT), - - I2C_TIMING_400_kHz = (0x00 << I2C_TIMINGR_PRESC_SHIFT) - + (0x03 << I2C_TIMINGR_SCLDEL_SHIFT) - + (0x01 << I2C_TIMINGR_SDADEL_SHIFT) - + (0x03 << I2C_TIMINGR_SCLH_SHIFT) - + (0x09 << I2C_TIMINGR_SCLL_SHIFT), - - I2C_TIMING_500_kHz = (0x00 << I2C_TIMINGR_PRESC_SHIFT) - + (0x01 << I2C_TIMINGR_SCLDEL_SHIFT) - + (0x01 << I2C_TIMINGR_SDADEL_SHIFT) - + (0x03 << I2C_TIMINGR_SCLH_SHIFT) - + (0x06 << I2C_TIMINGR_SCLL_SHIFT), -} i2c_timing; - -/* - * For internal use - */ - -static inline uint32 _i2c_bus_clk(i2c_dev *dev) { /* FIXME remove, is a remainder of F1 code */ - /* Both I2C peripherals are on APB1 */ - return STM32_PCLK1 / (1000 * 1000); -} - -extern uint8 i2c_read(i2c_dev *dev); - -#ifdef __cplusplus -} -#endif - -#endif /* _LIBMAPLE_STM32F3_I2C_H_ */ diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/nvic.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/nvic.h deleted file mode 100644 index 7643c32..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/nvic.h +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/nvic.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Nested Vectored Interrupt Controller (NVIC) support. - */ - -#ifndef _LIBMAPLE_STM32F3_NVIC_H_ -#define _LIBMAPLE_STM32F3_NVIC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -/** - * @brief STM32F1 interrupt vector table interrupt numbers. - * @see - */ -typedef enum nvic_irq_num { - NVIC_NMI = -14, /**< Non-maskable interrupt */ - NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */ - NVIC_MEM_MANAGE = -12, /**< Memory management */ - NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory - access fault. */ - NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction or - illegal state. */ - NVIC_SVC = -5, /**< System service call via SWI insruction */ - NVIC_DEBUG_MON = -4, /**< Debug monitor */ - NVIC_PEND_SVC = -2, /**< Pendable request for system service */ - NVIC_SYSTICK = -1, /**< System tick timer */ - - NVIC_WWDG = 0, /**< Window watchdog interrupt */ - NVIC_PVD = 1, /**< PVD through EXTI line detection */ - NVIC_TAMP_STAMP = 2, /**< Tamper */ - NVIC_RTC_WKUP = 3, /**< Real-time clock */ - NVIC_FLASH = 4, /**< Flash */ - NVIC_RCC = 5, /**< Reset and clock control */ - NVIC_EXTI0 = 6, /**< EXTI line 0 */ - NVIC_EXTI1 = 7, /**< EXTI line 1 */ - NVIC_EXTI2 = 8, /**< EXTI line 2 */ //FIXME capacitive touch - NVIC_EXTI3 = 9, /**< EXTI line 3 */ - NVIC_EXTI4 = 10, /**< EXTI line 4 */ - NVIC_DMA_CH1 = 11, /**< DMA1 channel 1 */ - NVIC_DMA_CH2 = 12, /**< DMA1 channel 2 */ - NVIC_DMA_CH3 = 13, /**< DMA1 channel 3 */ - NVIC_DMA_CH4 = 14, /**< DMA1 channel 4 */ - NVIC_DMA_CH5 = 15, /**< DMA1 channel 5 */ - NVIC_DMA_CH6 = 16, /**< DMA1 channel 6 */ - NVIC_DMA_CH7 = 17, /**< DMA1 channel 7 */ - NVIC_ADC1_2 = 18, /**< ADC1 and ADC2 */ - NVIC_USB_HP_CAN_TX = 19, /**< USB high priority or CAN TX */ - NVIC_USB_LP_CAN_RX0 = 20, /**< USB low priority or CAN RX0 */ - NVIC_CAN_RX1 = 21, /**< CAN RX1 */ - NVIC_CAN_SCE = 22, /**< CAN SCE */ - NVIC_EXTI_9_5 = 23, /**< EXTI line [9:5] */ - //NVIC_TIMER1_BRK_TIMER15 = 24, // FIXME hack - NVIC_TIMER1_BRK_TIMER9 = 24, /**< Timer 1 break, Timer 9. */ // FIXME rm - //NVIC_TIMER1_UP_TIMER16 = 25, // FIXME hack - NVIC_TIMER1_UP_TIMER10 = 25, /**< Timer 1 update, Timer 10. */ //FIXME rm - //NVIC_TIMER1_TRG_COM_TIMER17 = 26, // FIXME hack - NVIC_TIMER1_TRG_COM_TIMER11 = 26, /**< - * Timer 1 trigger and commutation, - * Timer 11. */ // FIXME rm - NVIC_TIMER1_CC = 27, /**< Timer 1 capture/compare */ - NVIC_TIMER2 = 28, /**< Timer 2 */ - NVIC_TIMER3 = 29, /**< Timer 3 */ - NVIC_TIMER4 = 30, /**< Timer 4 */ - NVIC_I2C1_EV = 31, /**< I2C1 event */ - NVIC_I2C1_ER = 32, /**< I2C1 error */ - NVIC_I2C2_EV = 33, /**< I2C2 event */ - NVIC_I2C2_ER = 34, /**< I2C2 error */ - NVIC_SPI1 = 35, /**< SPI1 */ - NVIC_SPI2 = 36, /**< SPI2 */ - NVIC_USART1 = 37, /**< USART1 */ - NVIC_USART2 = 38, /**< USART2 */ - NVIC_USART3 = 39, /**< USART3 */ - NVIC_EXTI_15_10 = 40, /**< EXTI line [15:10] */ - NVIC_RTC_ALARM = 41, /**< RTC alarm through EXTI line */ - NVIC_USB_WKUP = 42, /**< USB wakeup from suspend through - EXTI line */ - NVIC_TIMER8_BRK_TIMER12 = 43, /**< Timer 8 break, timer 12 */ //TODO rm TIMER12 - NVIC_TIMER8_UP_TIMER13 = 44, /**< Timer 8 update, timer 13 */ // TODO rm TIMER13 - NVIC_TIMER8_TRG_COM_TIMER14 = 45, /**< - * Timer 8 trigger and commutation, - * Timer 14. */ //TODO rm TIMER14 - NVIC_TIMER8_CC = 46, /**< Timer 8 capture/compare */ - NVIC_ADC3 = 47, /**< ADC3 */ - - NVIC_SPI3 = 51, /**< SPI3 */ - NVIC_UART4 = 52, /**< UART4 */ - NVIC_UART5 = 53, /**< UART5 */ - //NVIC_TIMER6_DAC = 54, // TODO hack - NVIC_TIMER6 = 54, /**< Timer 6 */ //TODO add DAC - NVIC_TIMER7 = 55, /**< Timer 7 */ - NVIC_DMA2_CH1 = 56, /**< DMA2 channel 1 */ - NVIC_DMA2_CH2 = 57, /**< DMA2 channel 2 */ - NVIC_DMA2_CH3 = 58, /**< DMA2 channel 3 */ - NVIC_DMA2_CH4 = 59, /**< DMA2 channel 4 */ - NVIC_DMA2_CH5 = 60, /**< DMA2 channel 5 */ - - NVIC_ADC4 = 61, /**< DMA2 channels 4 and 5 */ - - NVIC_COMP123 = 64, /**< DMA2 channels 4 and 5 */ - NVIC_COMP456 = 65, /**< DMA2 channels 4 and 5 */ - NVIC_COMP7 = 66, /**< DMA2 channels 4 and 5 */ - - NVIC_USB_HP = 74, /**< DMA2 channels 4 and 5 */ - NVIC_USB_LP = 75, /**< DMA2 channels 4 and 5 */ - NVIC_USB_WKUP2 = 76, /**< DMA2 channels 4 and 5 */ - - NVIC_FPU = 81, /**< DMA2 channels 4 and 5 */ -} nvic_irq_num; - -static inline void nvic_irq_disable_all(void) { - NVIC_BASE->ICER[0] = 0xFFFFFFFF; - NVIC_BASE->ICER[1] = 0xFFFFFFFF; - NVIC_BASE->ICER[2] = 0xFFFFFFFF; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/opamp.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/opamp.h deleted file mode 100644 index 858f1d8..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/opamp.h +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/ompamp.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 Operational Amplifier support. - */ - -#ifndef _LIBMAPLE_STM32F3_OPAMP_H_ -#define _LIBMAPLE_STM32F3_OPAMP_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Register map - */ - -/* - * OpAmp individual register map type. - */ -typedef struct opamp_reg_map { - __io uint32 CSR; /**< */ -} opamp_reg_map; - -/** OpAmp device type. */ -typedef struct opamp_dev { - opamp_reg_map *regs; /**< Register map */ -} opamp_dev; - -/* - * Devices - */ - -extern const struct opamp_dev *OPAMP1; /* OpAmp amplifier 1 */ -extern const struct opamp_dev *OPAMP2; /* OpAmp amplifier 2 */ -extern const struct opamp_dev *OPAMP3; /* OpAmp amplifier 3 */ -extern const struct opamp_dev *OPAMP4; /* OpAmp amplifier 4 */ - -/* - * Register map base pointers - */ - -#define OPAMP1_BASE ((struct opamp_reg_map*)0x40010038) -#define OPAMP2_BASE ((struct opamp_reg_map*)0x4001003C) -#define OPAMP3_BASE ((struct opamp_reg_map*)0x40010040) -#define OPAMP4_BASE ((struct opamp_reg_map*)0x40010044) - -/* - * Register bit definitions - */ - -/* Control and status register */ -#define OPAMP_CSR_LOCK_BIT 31 -#define OPAMP_CSR_OUTCAL_BIT 30 -#define OPAMP_CSR_TSTREF_BIT 29 -#define OPAMP_CSR_TRIMOFFSETN_SHIFT 24 -#define OPAMP_CSR_TRIMOFFSETP_SHIFT 19 -#define OPAMP_CSR_USER_TRIM_BIT 18 -#define OPAMP_CSR_PGA_GAIN_SHIFT 14 -#define OPAMP_CSR_CAL_SEL_SHIFT 12 -#define OPAMP_CSR_CAL_ON_BIT 11 -#define OPAMP_CSR_VPS_SEL_SHIFT 9 -#define OPAMP_CSR_VMS_SEL_BIT 8 -#define OPAMP_CSR_TCM_EN_BIT 7 -#define OPAMP_CSR_VM_SEL_SHIFT 5 -#define OPAMP_CSR_VP_SEL_SHIFT 2 -#define OPAMP_CSR_FORCE_VP_BIT 1 -#define OPAMP_CSR_EN_BIT 0 - -#define OPAMP_CSR_LOCK (1U << OPAMP_CSR_LOCK_BIT) -#define OPAMP_CSR_OUTCAL (1U << OPAMP_CSR_OUTCAL_BIT) -#define OPAMP_CSR_TSTREF (1U << OPAMP_CSR_TSTREF_BIT) -#define COMP_CSR_TRIMOFFSETN (0x1F << COMP_CSR_TRIMOFFSETN_SHIFT) -#define COMP_CSR_TRIMOFFSETP (0x1F << COMP_CSR_TRIMOFFSETP_SHIFT) -#define OPAMP_CSR_USER_TRIM (1U << OPAMP_CSR_USER_TRIM_BIT) -#define COMP_CSR_PGA_GAIN (0xF << COMP_CSR_PGA_GAIN_SHIFT) -#define COMP_CSR_CAL_SEL (0x3 << COMP_CSR_CAL_SEL_SHIFT) -#define OPAMP_CSR_CAL_ON (1U << OPAMP_CSR_CAL_ON_BIT) -#define COMP_CSR_VPS_SEL (0x3 << COMP_CSR_VPS_SEL_SHIFT) -#define OPAMP_CSR_VMS_SEL (1U << OPAMP_CSR_VMS_SEL_BIT) -#define OPAMP_CSR_TCM_EN (1U << OPAMP_CSR_TCM_EN_BIT) -#define COMP_CSR_VM_SEL (0x3 << COMP_CSR_VM_SEL_SHIFT) -#define COMP_CSR_VP_SEL (0x3 << COMP_CSR_VP_SEL_SHIFT) -#define OPAMP_CSR_FORCE_VP (1U << OPAMP_CSR_FORCE_VP_BIT) -#define OPAMP_CSR_EN (1U << OPAMP_CSR_EN_BIT) - -/* TODO - * actually implement me ;-) - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/pwr.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/pwr.h deleted file mode 100644 index d3564e8..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/pwr.h +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f1/include/series/pwr.h - * @author Marti Bolivar - * @brief STM32F3 Power control (PWR) support. - */ - -#ifndef _LIBMAPLE_STM32F3_PWR_H_ -#define _LIBMAPLE_STM32F3_PWR_H_ - -/* - * Register bit definitions - */ - -/* Control register */ - -/* PVD level selection */ -#define PWR_CR_PLS_2_2V (0x0 << 5) -#define PWR_CR_PLS_2_3V (0x1 << 5) -#define PWR_CR_PLS_2_4V (0x2 << 5) -#define PWR_CR_PLS_2_5V (0x3 << 5) -#define PWR_CR_PLS_2_6V (0x4 << 5) -#define PWR_CR_PLS_2_7V (0x5 << 5) -#define PWR_CR_PLS_2_8V (0x6 << 5) -#define PWR_CR_PLS_2_9V (0x7 << 5) - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/rcc.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/rcc.h deleted file mode 100644 index 80577e9..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/rcc.h +++ /dev/null @@ -1,632 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/rcc.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 reset and clock control (RCC) support. - */ - -#ifndef _LIBMAPLE_STM32F3_RCC_H_ -#define _LIBMAPLE_STM32F3_RCC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Register map - */ - -/** STM32F3 RCC register map type */ -typedef struct rcc_reg_map { - __io uint32 CR; /**< Clock control register */ - __io uint32 CFGR; /**< Clock configuration register */ - __io uint32 CIR; /**< Clock interrupt register */ - __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ - __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ - __io uint32 AHBENR; /**< AHB peripheral clock enable register */ - __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ - __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ - __io uint32 BDCR; /**< Backup domain control register */ - __io uint32 CSR; /**< Control/status register */ - __io uint32 AHBRSTR; /**< AHB peripheral reset register */ - __io uint32 CFGR2; /**< Control/status register 2 */ - __io uint32 CFGR3; /**< Control/status register 3 */ -} rcc_reg_map; - -#define RCC_BASE ((struct rcc_reg_map*)0x40021000) - -/* - * Register bit definitions - */ - -/* Clock control register */ - -#define RCC_CR_PLLRDY_BIT 25 -#define RCC_CR_PLLON_BIT 24 -#define RCC_CR_CSSON_BIT 19 -#define RCC_CR_HSEBYP_BIT 18 -#define RCC_CR_HSERDY_BIT 17 -#define RCC_CR_HSEON_BIT 16 -#define RCC_CR_HSIRDY_BIT 1 -#define RCC_CR_HSION_BIT 0 - -#define RCC_CR_PLLRDY (1U << RCC_CR_PLLRDY_BIT) -#define RCC_CR_PLLON (1U << RCC_CR_PLLON_BIT) -#define RCC_CR_CSSON (1U << RCC_CR_CSSON_BIT) -#define RCC_CR_HSEBYP (1U << RCC_CR_HSEBYP_BIT) -#define RCC_CR_HSERDY (1U << RCC_CR_HSERDY_BIT) -#define RCC_CR_HSEON (1U << RCC_CR_HSEON_BIT) -#define RCC_CR_HSICAL (0xFF << 8) -#define RCC_CR_HSITRIM (0x1F << 3) -#define RCC_CR_HSIRDY (1U << RCC_CR_HSIRDY_BIT) -#define RCC_CR_HSION (1U << RCC_CR_HSION_BIT) - -/* Clock configuration register */ - -#define RCC_CFGR_I2SSRC_BIT 23 -#define RCC_CFGR_USBPRE_BIT 22 -#define RCC_CFGR_PLLMUL_BIT 18 -#define RCC_CFGR_PLLXTPRE_BIT 17 -#define RCC_CFGR_PLLSRC_BIT 16 -#define RCC_CFGR_PPRE2_BIT 11 -#define RCC_CFGR_PPRE1_BIT 8 -#define RCC_CFGR_HPRE_BIT 4 - -#define RCC_CFGR_MCO (0x3 << 24) -#define RCC_CFGR_I2SSRC (1U << RCC_CFGR_I2CSRC_BIT) -#define RCC_CFGR_USBPRE (1U << RCC_CFGR_USBPRE_BIT) -#define RCC_CFGR_PLLMUL (0xF << RCC_CFGR_PLLMUL_BIT) -#define RCC_CFGR_PLLXTPRE (1U << RCC_CFGR_PLLXTPRE_BIT) -#define RCC_CFGR_PLLSRC (1U << RCC_CFGR_PLLSRC_BIT) -#define RCC_CFGR_PPRE2 (0x7 << RCC_CFGR_PPRE2_BIT) -#define RCC_CFGR_PPRE1 (0x7 << RCC_CFGR_PPRE1_BIT) -#define RCC_CFGR_HPRE (0xF << RCC_CFGR_HPRE_BIT) -#define RCC_CFGR_SWS (0x3 << 2) -#define RCC_CFGR_SWS_PLL (0x2 << 2) -#define RCC_CFGR_SWS_HSE (0x1 << 2) -#define RCC_CFGR_SW 0x3 -#define RCC_CFGR_SW_PLL 0x2 -#define RCC_CFGR_SW_HSE 0x1 - -/* Clock interrupt register */ - -#define RCC_CIR_CSSC_BIT 23 -#define RCC_CIR_PLLRDYC_BIT 20 -#define RCC_CIR_HSERDYC_BIT 19 -#define RCC_CIR_HSIRDYC_BIT 18 -#define RCC_CIR_LSERDYC_BIT 17 -#define RCC_CIR_LSIRDYC_BIT 16 -#define RCC_CIR_PLLRDYIE_BIT 12 -#define RCC_CIR_HSERDYIE_BIT 11 -#define RCC_CIR_HSIRDYIE_BIT 10 -#define RCC_CIR_LSERDYIE_BIT 9 -#define RCC_CIR_LSIRDYIE_BIT 8 -#define RCC_CIR_CSSF_BIT 7 -#define RCC_CIR_PLLRDYF_BIT 4 -#define RCC_CIR_HSERDYF_BIT 3 -#define RCC_CIR_HSIRDYF_BIT 2 -#define RCC_CIR_LSERDYF_BIT 1 -#define RCC_CIR_LSIRDYF_BIT 0 - -#define RCC_CIR_CSSC (1U << RCC_CIR_CSSC_BIT) -#define RCC_CIR_PLLRDYC (1U << RCC_CIR_PLLRDYC_BIT) -#define RCC_CIR_HSERDYC (1U << RCC_CIR_HSERDYC_BIT) -#define RCC_CIR_HSIRDYC (1U << RCC_CIR_HSIRDYC_BIT) -#define RCC_CIR_LSERDYC (1U << RCC_CIR_LSERDYC_BIT) -#define RCC_CIR_LSIRDYC (1U << RCC_CIR_LSIRDYC_BIT) -#define RCC_CIR_PLLRDYIE (1U << RCC_CIR_PLLRDYIE_BIT) -#define RCC_CIR_HSERDYIE (1U << RCC_CIR_HSERDYIE_BIT) -#define RCC_CIR_HSIRDYIE (1U << RCC_CIR_HSIRDYIE_BIT) -#define RCC_CIR_LSERDYIE (1U << RCC_CIR_LSERDYIE_BIT) -#define RCC_CIR_LSIRDYIE (1U << RCC_CIR_LSIRDYIE_BIT) -#define RCC_CIR_CSSF (1U << RCC_CIR_CSSF_BIT) -#define RCC_CIR_PLLRDYF (1U << RCC_CIR_PLLRDYF_BIT) -#define RCC_CIR_HSERDYF (1U << RCC_CIR_HSERDYF_BIT) -#define RCC_CIR_HSIRDYF (1U << RCC_CIR_HSIRDYF_BIT) -#define RCC_CIR_LSERDYF (1U << RCC_CIR_LSERDYF_BIT) -#define RCC_CIR_LSIRDYF (1U << RCC_CIR_LSIRDYF_BIT) - -/* APB2 peripheral reset register */ - -#define RCC_APB2RSTR_TIM17RST_BIT 18 -#define RCC_APB2RSTR_TIM16RST_BIT 17 -#define RCC_APB2RSTR_TIM15RST_BIT 16 -#define RCC_APB2RSTR_USART1RST_BIT 14 -#define RCC_APB2RSTR_TIM8RST_BIT 13 -#define RCC_APB2RSTR_SPI1RST_BIT 12 -#define RCC_APB2RSTR_TIM1RST_BIT 11 -#define RCC_APB2RSTR_SYSCFGRST_BIT 0 - -#define RCC_APB2RSTR_TIM17RST (1U << RCC_APB2RSTR_TIM17RST_BIT) -#define RCC_APB2RSTR_TIM16RST (1U << RCC_APB2RSTR_TIM16RST_BIT) -#define RCC_APB2RSTR_TIM15RST (1U << RCC_APB2RSTR_TIM15RST_BIT) -#define RCC_APB2RSTR_USART1RST (1U << RCC_APB2RSTR_USART1RST_BIT) -#define RCC_APB2RSTR_TIM8RST (1U << RCC_APB2RSTR_TIM8RST_BIT) -#define RCC_APB2RSTR_SPI1RST (1U << RCC_APB2RSTR_SPI1RST_BIT) -#define RCC_APB2RSTR_TIM1RST (1U << RCC_APB2RSTR_TIM1RST_BIT) -#define RCC_APB2RSTR_SYSCFGRST (1U << RCC_APB2RSTR_SYSCFGRST_BIT) - -/* APB1 peripheral reset register */ - -#define RCC_APB1RSTR_DACRST_BIT 29 -#define RCC_APB1RSTR_PWRRST_BIT 28 -#define RCC_APB1RSTR_CANRST_BIT 25 -#define RCC_APB1RSTR_USBRST_BIT 23 -#define RCC_APB1RSTR_I2C2RST_BIT 22 -#define RCC_APB1RSTR_I2C1RST_BIT 21 -#define RCC_APB1RSTR_UART5RST_BIT 20 -#define RCC_APB1RSTR_UART4RST_BIT 19 -#define RCC_APB1RSTR_USART3RST_BIT 18 -#define RCC_APB1RSTR_USART2RST_BIT 17 -#define RCC_APB1RSTR_SPI3RST_BIT 15 -#define RCC_APB1RSTR_SPI2RST_BIT 14 -#define RCC_APB1RSTR_WWDRST_BIT 11 -#define RCC_APB1RSTR_TIM7RST_BIT 5 -#define RCC_APB1RSTR_TIM6RST_BIT 4 -#define RCC_APB1RSTR_TIM4RST_BIT 2 -#define RCC_APB1RSTR_TIM3RST_BIT 1 -#define RCC_APB1RSTR_TIM2RST_BIT 0 - -#define RCC_APB1RSTR_DACRST (1U << RCC_APB1RSTR_DACRST_BIT) -#define RCC_APB1RSTR_PWRRST (1U << RCC_APB1RSTR_PWRRST_BIT) -#define RCC_APB1RSTR_CANRST (1U << RCC_APB1RSTR_CANRST_BIT) -#define RCC_APB1RSTR_USBRST (1U << RCC_APB1RSTR_USBRST_BIT) -#define RCC_APB1RSTR_I2C2RST (1U << RCC_APB1RSTR_I2C2RST_BIT) -#define RCC_APB1RSTR_I2C1RST (1U << RCC_APB1RSTR_I2C1RST_BIT) -#define RCC_APB1RSTR_UART5RST (1U << RCC_APB1RSTR_UART5RST_BIT) -#define RCC_APB1RSTR_UART4RST (1U << RCC_APB1RSTR_UART4RST_BIT) -#define RCC_APB1RSTR_USART3RST (1U << RCC_APB1RSTR_USART3RST_BIT) -#define RCC_APB1RSTR_USART2RST (1U << RCC_APB1RSTR_USART2RST_BIT) -#define RCC_APB1RSTR_SPI3RST (1U << RCC_APB1RSTR_SPI3RST_BIT) -#define RCC_APB1RSTR_SPI2RST (1U << RCC_APB1RSTR_SPI2RST_BIT) -#define RCC_APB1RSTR_WWDRST (1U << RCC_APB1RSTR_WWDRST_BIT) -#define RCC_APB1RSTR_TIM7RST (1U << RCC_APB1RSTR_TIM7RST_BIT) -#define RCC_APB1RSTR_TIM6RST (1U << RCC_APB1RSTR_TIM6RST_BIT) -#define RCC_APB1RSTR_TIM4RST (1U << RCC_APB1RSTR_TIM4RST_BIT) -#define RCC_APB1RSTR_TIM3RST (1U << RCC_APB1RSTR_TIM3RST_BIT) -#define RCC_APB1RSTR_TIM2RST (1U << RCC_APB1RSTR_TIM2RST_BIT) - -/* AHB peripheral clock enable register */ - -#define RCC_AHBENR_ADC34EN_BIT 29 -#define RCC_AHBENR_ADC12EN_BIT 28 -#define RCC_AHBENR_TSCEN_BIT 24 -#define RCC_AHBENR_IOPFEN_BIT 22 -#define RCC_AHBENR_IOPEEN_BIT 21 -#define RCC_AHBENR_IOPDEN_BIT 20 -#define RCC_AHBENR_IOPCEN_BIT 19 -#define RCC_AHBENR_IOPBEN_BIT 18 -#define RCC_AHBENR_IOPAEN_BIT 17 -#define RCC_AHBENR_CRCEN_BIT 6 -#define RCC_AHBENR_FLITFEN_BIT 4 -#define RCC_AHBENR_SRAMEN_BIT 2 -#define RCC_AHBENR_DMA2EN_BIT 1 -#define RCC_AHBENR_DMA1EN_BIT 0 - -#define RCC_AHBENR_ADC34EN (1U << RCC_AHBENR_ADC34EN_BIT) -#define RCC_AHBENR_ADC12EN (1U << RCC_AHBENR_ADC12EN_BIT) -#define RCC_AHBENR_TSCEN (1U << RCC_AHBENR_TSCEN_BIT) -#define RCC_AHBENR_IOPFEN (1U << RCC_AHBENR_IOPFEN_BIT) -#define RCC_AHBENR_IOPEEN (1U << RCC_AHBENR_IOPEEN_BIT) -#define RCC_AHBENR_IOPDEN (1U << RCC_AHBENR_IOPDEN_BIT) -#define RCC_AHBENR_IOPCEN (1U << RCC_AHBENR_IOPCEN_BIT) -#define RCC_AHBENR_IOPBEN (1U << RCC_AHBENR_IOPBEN_BIT) -#define RCC_AHBENR_IOPAEN (1U << RCC_AHBENR_IOPAEN_BIT) -#define RCC_AHBENR_CRCEN (1U << RCC_AHBENR_CRCEN_BIT) -#define RCC_AHBENR_FLITFEN (1U << RCC_AHBENR_FLITFEN_BIT) -#define RCC_AHBENR_SRAMEN (1U << RCC_AHBENR_SRAMEN_BIT) -#define RCC_AHBENR_DMA2EN (1U << RCC_AHBENR_DMA2EN_BIT) -#define RCC_AHBENR_DMA1EN (1U << RCC_AHBENR_DMA1EN_BIT) - -/* APB2 peripheral clock enable register */ - -#define RCC_APB2ENR_TIM17EN_BIT 18 -#define RCC_APB2ENR_TIM16EN_BIT 17 -#define RCC_APB2ENR_TIM15EN_BIT 16 -#define RCC_APB2ENR_USART1EN_BIT 14 -#define RCC_APB2ENR_TIM8EN_BIT 13 -#define RCC_APB2ENR_SPI1EN_BIT 12 -#define RCC_APB2ENR_TIM1EN_BIT 11 -#define RCC_APB2ENR_SYSCFGEN_BIT 0 - -#define RCC_APB2ENR_TIM17EN (1U << RCC_APB2ENR_TIM17EN_BIT) -#define RCC_APB2ENR_TIM16EN (1U << RCC_APB2ENR_TIM16EN_BIT) -#define RCC_APB2ENR_TIM15EN (1U << RCC_APB2ENR_TIM15EN_BIT) -#define RCC_APB2ENR_USART1EN (1U << RCC_APB2ENR_USART1EN_BIT) -#define RCC_APB2ENR_TIM8EN (1U << RCC_APB2ENR_TIM8EN_BIT) -#define RCC_APB2ENR_SPI1EN (1U << RCC_APB2ENR_SPI1EN_BIT) -#define RCC_APB2ENR_TIM1EN (1U << RCC_APB2ENR_TIM1EN_BIT) -#define RCC_APB2ENR_SYSCFGEN (1U << RCC_APB2ENR_SYSCFGEN_BIT) - -/* APB1 peripheral clock enable register */ - -#define RCC_APB1ENR_DACEN_BIT 29 -#define RCC_APB1ENR_PWREN_BIT 28 -#define RCC_APB1ENR_CANEN_BIT 25 -#define RCC_APB1ENR_USBEN_BIT 23 -#define RCC_APB1ENR_I2C2EN_BIT 22 -#define RCC_APB1ENR_I2C1EN_BIT 21 -#define RCC_APB1ENR_UART5EN_BIT 20 -#define RCC_APB1ENR_UART4EN_BIT 19 -#define RCC_APB1ENR_USART3EN_BIT 18 -#define RCC_APB1ENR_USART2EN_BIT 17 -#define RCC_APB1ENR_SPI3EN_BIT 15 -#define RCC_APB1ENR_SPI2EN_BIT 14 -#define RCC_APB1ENR_WWDEN_BIT 11 -#define RCC_APB1ENR_TIM7EN_BIT 5 -#define RCC_APB1ENR_TIM6EN_BIT 4 -#define RCC_APB1ENR_TIM4EN_BIT 2 -#define RCC_APB1ENR_TIM3EN_BIT 1 -#define RCC_APB1ENR_TIM2EN_BIT 0 - -#define RCC_APB1ENR_DACEN (1U << RCC_APB1ENR_DACEN_BIT) -#define RCC_APB1ENR_PWREN (1U << RCC_APB1ENR_PWREN_BIT) -#define RCC_APB1ENR_CANEN (1U << RCC_APB1ENR_CANEN_BIT) -#define RCC_APB1ENR_USBEN (1U << RCC_APB1ENR_USBEN_BIT) -#define RCC_APB1ENR_I2C2EN (1U << RCC_APB1ENR_I2C2EN_BIT) -#define RCC_APB1ENR_I2C1EN (1U << RCC_APB1ENR_I2C1EN_BIT) -#define RCC_APB1ENR_UART5EN (1U << RCC_APB1ENR_UART5EN_BIT) -#define RCC_APB1ENR_UART4EN (1U << RCC_APB1ENR_UART4EN_BIT) -#define RCC_APB1ENR_USART3EN (1U << RCC_APB1ENR_USART3EN_BIT) -#define RCC_APB1ENR_USART2EN (1U << RCC_APB1ENR_USART2EN_BIT) -#define RCC_APB1ENR_SPI3EN (1U << RCC_APB1ENR_SPI3EN_BIT) -#define RCC_APB1ENR_SPI2EN (1U << RCC_APB1ENR_SPI2EN_BIT) -#define RCC_APB1ENR_WWDEN (1U << RCC_APB1ENR_WWDEN_BIT) -#define RCC_APB1ENR_TIM7EN (1U << RCC_APB1ENR_TIM7EN_BIT) -#define RCC_APB1ENR_TIM6EN (1U << RCC_APB1ENR_TIM6EN_BIT) -#define RCC_APB1ENR_TIM4EN (1U << RCC_APB1ENR_TIM4EN_BIT) -#define RCC_APB1ENR_TIM3EN (1U << RCC_APB1ENR_TIM3EN_BIT) -#define RCC_APB1ENR_TIM2EN (1U << RCC_APB1ENR_TIM2EN_BIT) - -/* Backup domain control register */ - -#define RCC_BDCR_BDRST_BIT 16 -#define RCC_BDCR_RTCEN_BIT 15 -#define RCC_BDCR_LSEBYP_BIT 2 -#define RCC_BDCR_LSERDY_BIT 1 -#define RCC_BDCR_LSEON_BIT 0 - -#define RCC_BDCR_BDRST (1U << RCC_BDCR_BDRST_BIT) -#define RCC_BDCR_RTCEN (1U << RCC_BDCR_RTC_BIT) -#define RCC_BDCR_RTCSEL (0x3 << 8) -#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) -#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) -#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) -#define RCC_BDCR_LSEBYP (1U << RCC_BDCR_LSEBYP_BIT) -#define RCC_BDCR_LSERDY (1U << RCC_BDCR_LSERDY_BIT) -#define RCC_BDCR_LSEON (1U << RCC_BDCR_LSEON_BIT) - -/* Control/status register */ - -#define RCC_CSR_LPWRRSTF_BIT 31 -#define RCC_CSR_WWDGRSTF_BIT 30 -#define RCC_CSR_IWDGRSTF_BIT 29 -#define RCC_CSR_SFTRSTF_BIT 28 -#define RCC_CSR_PORRSTF_BIT 27 -#define RCC_CSR_PINRSTF_BIT 26 -#define RCC_CSR_OBLRSTF_BIT 25 -#define RCC_CSR_RMVF_BIT 24 -#define RCC_CSR_LSIRDY_BIT 1 -#define RCC_CSR_LSION_BIT 0 - -#define RCC_CSR_LPWRRSTF (1U << RCC_CSR_LPWRRSTF_BIT) -#define RCC_CSR_WWDGRSTF (1U << RCC_CSR_WWDGRSTF_BIT) -#define RCC_CSR_IWDGRSTF (1U << RCC_CSR_IWDGRSTF_BIT) -#define RCC_CSR_SFTRSTF (1U << RCC_CSR_SFTRSTF_BIT) -#define RCC_CSR_PORRSTF (1U << RCC_CSR_PORRSTF_BIT) -#define RCC_CSR_PINRSTF (1U << RCC_CSR_PINRSTF_BIT) -#define RCC_CSR_OBLRSTF (1U << RCC_CSR_OBLRSTF_BIT) -#define RCC_CSR_RMVF (1U << RCC_CSR_RMVF_BIT) -#define RCC_CSR_LSIRDY (1U << RCC_CSR_LSIRDY_BIT) -#define RCC_CSR_LSION (1U << RCC_CSR_LSION_BIT) - -/* AHB peripheral reset register */ - -#define RCC_AHBRSTR_ADC34RST_BIT 29 -#define RCC_AHBRSTR_ADC12RST_BIT 28 -#define RCC_AHBRSTR_TSCRST_BIT 24 -#define RCC_AHBRSTR_IOPFRST_BIT 22 -#define RCC_AHBRSTR_IOPERST_BIT 21 -#define RCC_AHBRSTR_IOPDRST_BIT 20 -#define RCC_AHBRSTR_IOPCRST_BIT 19 -#define RCC_AHBRSTR_IOPBRST_BIT 18 -#define RCC_AHBRSTR_IOPARST_BIT 17 - -#define RCC_AHBRSTR_ADC34RST (1U << RCC_AHBRSTR_ADC34RST_BIT) -#define RCC_AHBRSTR_ADC12RST (1U << RCC_AHBRSTR_ADC12RST_BIT) -#define RCC_AHBRSTR_TSCRST (1U << RCC_AHBRSTR_TSCRST_BIT) -#define RCC_AHBRSTR_IOPFRST (1U << RCC_AHBRSTR_IOPFRST_BIT) -#define RCC_AHBRSTR_IOPERST (1U << RCC_AHBRSTR_IOPERST_BIT) -#define RCC_AHBRSTR_IOPDRST (1U << RCC_AHBRSTR_IOPDRST_BIT) -#define RCC_AHBRSTR_IOPCRST (1U << RCC_AHBRSTR_IOPCRST_BIT) -#define RCC_AHBRSTR_IOPBRST (1U << RCC_AHBRSTR_IOPBRST_BIT) -#define RCC_AHBRSTR_IOPARST (1U << RCC_AHBRSTR_IOPARST_BIT) - -/* Clock configuration register 2 */ - -#define RCC_CFGR2_ADC34PRES_SHIFT 9 -#define RCC_CFGR2_ADC12PRES_SHIFT 4 - -#define RCC_CFGR2_ADC34PRES (0x1f << RCC_CFGR2_ADC34PRES_SHIFT) -#define RCC_CFGR2_ADC12PRES (0x1f << RCC_CFGR2_ADC12PRES_SHIFT) -#define RCC_CFGR2_PREDIV 0xf - -/* Clock configuration register 3 */ //TODO make clock sources configurable - -#define RCC_CFGR3_TIM8SW_BIT 9 -#define RCC_CFGR3_TIM1SW_BIT 8 -#define RCC_CFGR3_I2C2SW_BIT 5 -#define RCC_CFGR3_I2C1SW_BIT 4 - -#define RCC_CFGR3_UART5SW (0x3 << 22) -#define RCC_CFGR3_UART4SW (0x3 << 20) -#define RCC_CFGR3_USART3SW (0x3 << 18) -#define RCC_CFGR3_USART2SW (0x3 << 16) -#define RCC_CFGR_TIM8SW (1U << RCC_CFGR3_TIM8SW_BIT) -#define RCC_CFGR_TIM1SW (1U << RCC_CFGR3_TIM1SW_BIT) -#define RCC_CFGR_I2C2SW (1U << RCC_CFGR3_I2C2SW_BIT) -#define RCC_CFGR_I2C1SW (1U << RCC_CFGR3_I2C1SW_BIT) -#define RCC_CFGR3_USART1SW 0x3 - -/* - * libmaple-mandated enumeration types. - */ - -/** - * @brief STM32F3 rcc_clk_id. - */ -typedef enum rcc_clk_id { - RCC_GPIOA, - RCC_GPIOB, - RCC_GPIOC, - RCC_GPIOD, - RCC_GPIOE, - RCC_GPIOF, - - RCC_ADC12, - RCC_ADC34, - - RCC_DAC, - - RCC_DMA1, - RCC_DMA2, - - RCC_I2C1, - RCC_I2C2, - - RCC_SPI1, - RCC_SPI2, - RCC_SPI3, - - RCC_USART1, - RCC_USART2, - RCC_USART3, - RCC_UART4, - RCC_UART5, - - RCC_TIMER1, - RCC_TIMER2, - RCC_TIMER3, - RCC_TIMER4, - RCC_TIMER5, - RCC_TIMER6, - RCC_TIMER7, - RCC_TIMER8, - RCC_TIMER9, - RCC_TIMER10, - RCC_TIMER11, - RCC_TIMER12, - RCC_TIMER13, - RCC_TIMER14, - RCC_TIMER15, - RCC_TIMER16, - RCC_TIMER17, - - RCC_SYSCFG, - RCC_CRC, - RCC_FLITF, - RCC_PWR, - RCC_SRAM, - RCC_USB, -} rcc_clk_id; - -/** - * @brief STM32F3 PLL clock sources. - * @see rcc_configure_pll() - */ -typedef enum rcc_pllsrc { - RCC_PLLSRC_HSE = (0x1 << RCC_CFGR_PLLSRC_BIT), - RCC_PLLSRC_HSI_DIV_2 = (0x0 << RCC_CFGR_PLLSRC_BIT) -} rcc_pllsrc; - -/** - * @brief STM32F3 clock domains. - * @see rcc_dev_clk() - */ -typedef enum rcc_clk_domain { - RCC_APB1, - RCC_APB2, - RCC_AHB -} rcc_clk_domain; - -/** - * @brief STM32F3 Prescaler identifiers - * @see rcc_set_prescaler() - */ -typedef enum rcc_prescaler { - RCC_PRESCALER_AHB, - RCC_PRESCALER_APB1, - RCC_PRESCALER_APB2, - RCC_PRESCALER_USB, -} rcc_prescaler; - -/** - * @brief STM32F3 ADC prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_adc_divider { - RCC_ADCPRE_PCLK_DISABLED = 0x00, - RCC_ADCPRE_PCLK_DIV_1 = 0x10, - RCC_ADCPRE_PCLK_DIV_2 = 0x11, - RCC_ADCPRE_PCLK_DIV_4 = 0x12, - RCC_ADCPRE_PCLK_DIV_6 = 0x13, - RCC_ADCPRE_PCLK_DIV_8 = 0x14, - RCC_ADCPRE_PCLK_DIV_10 = 0x15, - RCC_ADCPRE_PCLK_DIV_12 = 0x16, - RCC_ADCPRE_PCLK_DIV_16 = 0x17, - RCC_ADCPRE_PCLK_DIV_32 = 0x18, - RCC_ADCPRE_PCLK_DIV_64 = 0x19, - RCC_ADCPRE_PCLK_DIV_128 = 0x1A, - RCC_ADCPRE_PCLK_DIV_256 = 0x1B, -} rcc_adc_divider; - -/** - * @brief STM32F3 PREDIV prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_prediv_divider { - RCC_PREDIV_PCLK_DIV_1 = 0x0, - RCC_PREDIV_PCLK_DIV_2 = 0x1, - RCC_PREDIV_PCLK_DIV_3 = 0x2, - RCC_PREDIV_PCLK_DIV_4 = 0x3, - RCC_PREDIV_PCLK_DIV_5 = 0x4, - RCC_PREDIV_PCLK_DIV_6 = 0x5, - RCC_PREDIV_PCLK_DIV_7 = 0x6, - RCC_PREDIV_PCLK_DIV_8 = 0x7, - RCC_PREDIV_PCLK_DIV_9 = 0x8, - RCC_PREDIV_PCLK_DIV_10 = 0x9, - RCC_PREDIV_PCLK_DIV_11 = 0xA, - RCC_PREDIV_PCLK_DIV_12 = 0xB, - RCC_PREDIV_PCLK_DIV_13 = 0xC, - RCC_PREDIV_PCLK_DIV_14 = 0xD, - RCC_PREDIV_PCLK_DIV_15 = 0xE, - RCC_PREDIV_PCLK_DIV_16 = 0xF, -} rcc_prediv_divider; - -/** - * @brief STM32F3 APB1 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb1_divider { - RCC_APB1_HCLK_DIV_1 = 0x0 << RCC_CFGR_PPRE1_BIT, - RCC_APB1_HCLK_DIV_2 = 0x4 << RCC_CFGR_PPRE1_BIT, - RCC_APB1_HCLK_DIV_4 = 0x5 << RCC_CFGR_PPRE1_BIT, - RCC_APB1_HCLK_DIV_8 = 0x6 << RCC_CFGR_PPRE1_BIT, - RCC_APB1_HCLK_DIV_16 = 0x7 << RCC_CFGR_PPRE1_BIT, -} rcc_apb1_divider; - -/** - * @brief STM32F3 APB2 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb2_divider { - RCC_APB2_HCLK_DIV_1 = 0x0 << RCC_CFGR_PPRE2_BIT, - RCC_APB2_HCLK_DIV_2 = 0x4 << RCC_CFGR_PPRE2_BIT, - RCC_APB2_HCLK_DIV_4 = 0x5 << RCC_CFGR_PPRE2_BIT, - RCC_APB2_HCLK_DIV_8 = 0x6 << RCC_CFGR_PPRE2_BIT, - RCC_APB2_HCLK_DIV_16 = 0x7 << RCC_CFGR_PPRE2_BIT, -} rcc_apb2_divider; - -/** - * @brief STM32F3 AHB prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_ahb_divider { - RCC_AHB_SYSCLK_DIV_1 = 0x0 << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_2 = 0x8 << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_4 = 0x9 << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_8 = 0xA << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_16 = 0xB << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_32 = 0xC << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_64 = 0xD << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_128 = 0xD << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_256 = 0xE << RCC_CFGR_HPRE_BIT, - RCC_AHB_SYSCLK_DIV_512 = 0xF << RCC_CFGR_HPRE_BIT, -} rcc_ahb_divider; - -/** - * @brief STM32F3 clock sources. - */ -typedef enum rcc_clk { - RCC_CLK_PLL = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | - RCC_CR_PLLON_BIT), /**< Main PLL, clocked by - HSI or HSE. */ - RCC_CLK_HSE = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | - RCC_CR_HSEON_BIT), /**< High speed external. */ - RCC_CLK_HSI = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | - RCC_CR_HSION_BIT), /**< High speed internal. */ - RCC_CLK_LSE = (uint16)((offsetof(struct rcc_reg_map, BDCR) << 8) | - RCC_BDCR_LSEON_BIT), /**< Low-speed external - * (32.768 KHz). */ - RCC_CLK_LSI = (uint16)((offsetof(struct rcc_reg_map, CSR) << 8) | - RCC_CSR_LSION_BIT), /**< Low-speed internal - * (approximately 32 KHz). */ -} rcc_clk; - -/** - * @brief STM32F3 PLL multipliers. - */ -typedef enum rcc_pll_multiplier { - RCC_PLLMUL_2 = (0x0 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_3 = (0x1 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_4 = (0x2 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_5 = (0x3 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_6 = (0x4 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_7 = (0x5 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_8 = (0x6 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_9 = (0x7 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_10 = (0x8 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_11 = (0x9 << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_12 = (0xA << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_13 = (0xB << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_14 = (0xC << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_15 = (0xD << RCC_CFGR_PLLMUL_BIT), - RCC_PLLMUL_16 = (0xE << RCC_CFGR_PLLMUL_BIT), -} rcc_pll_multiplier; - -/* FIXME [0.0.13] Just have data point to an rcc_pll_multiplier! */ - -/** - * @brief STM32F3 PLL configuration values. - * Point to one of these with the "data" field in a struct rcc_pll_cfg. - * @see struct rcc_pll_cfg. - */ -typedef struct stm32f3_rcc_pll_data { - rcc_pll_multiplier pll_mul; /**< PLL multiplication factor. */ - rcc_prediv_divider pclk_prediv; /**< PCLK predivider. */ -} stm32f3_rcc_pll_data; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/simd.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/simd.h deleted file mode 100644 index 8325d5d..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/simd.h +++ /dev/null @@ -1,109 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/include/libmaple/simd.h - * @author F3-port by Hanspeter Portner - * @brief Convenience macros for the digital signal processing (DSP) - * instruction set of the ARM Cortex M4 microcontroller. - */ - -#ifndef _LIBMAPLE_DSP_H_ -#define _LIBMAPLE_DSP_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#define DSP3(ID, A, B, C) \ -({ \ - uint32_t X; \ - asm volatile (ID" %[res], %[val1], %[val2], %[val3]" \ - : [res]"=r" (X) \ - : [val1]"r" (A), [val2]"r" (B), [val3]"r" (C) \ - ); \ - (uint32_t)X; \ -}) - -#define DSP2(ID, A, B) \ -({ \ - uint32_t X; \ - asm volatile (ID" %[res], %[val1], %[val2]" \ - : [res]"=r" (X) \ - : [val1]"r" (A), [val2]"r" (B) \ - );\ - (uint32_t)X; \ -}) - -#define DSP1(ID, A) \ -({ \ - uint32_t X; \ - asm volatile (ID" %[res], %[val1]" \ - : [res]"=r" (X) \ - : [val1]"r" (A) \ - ); \ - (uint32_t)X; \ -}) - -/* General data processing instructions */ -#define __rev16(A) DSP1("REV16", A) - -/* SIMD instructions (single instruction multiple data) */ -#define __sadd16(A, B) DSP2("SADD16", A, B) -#define __shadd16(A, B) DSP2("SHADD16", A, B) -#define __ssub16(A, B) DSP2("SSUB16", A, B) -#define __shsub16(A, B) DSP2("SHSUB16", A, B) -#define __uadd16(A, B) DSP2("UADD16", A, B) -#define __uhadd16(A, B) DSP2("UHADD16", A, B) -#define __usub16(A, B) DSP2("USUB16", A, B) -#define __uhsub16(A, B) DSP2("UHSUB16", A, B) - -#define __sadd8(A, B) DSP2("SADD8", A, B) -#define __shadd8(A, B) DSP2("SHADD8", A, B) -#define __ssub8(A, B) DSP2("SSUB8", A, B) -#define __shsub8(A, B) DSP2("SHSUB8", A, B) -#define __uadd8(A, B) DSP2("UADD8", A, B) -#define __uhadd8(A, B) DSP2("UHADD8", A, B) -#define __usub8(A, B) DSP2("USUB8", A, B) -#define __uhsub8(A, B) DSP2("UHSUB8", A, B) - -#define __sasx(A, B) DSP2("SASX", A, B) -#define __ssax(A, B) DSP2("SSAX", A, B) -#define __shasx(A, B) DSP2("SHASX", A, B) -#define __shsax(A, B) DSP2("SHSAX", A, B) -#define __uasx(A, B) DSP2("UASX", A, B) -#define __usax(A, B) DSP2("USAX", A, B) -#define __uhasx(A, B) DSP2("UHASX", A, B) -#define __uhsax(A, B) DSP2("UHSAX", A, B) - -#define __usad8(A, B) DSP2("USAD8", A, B) -#define __usada8(A, B, C) DSP3("USADA8", A, B, C) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/spi.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/spi.h deleted file mode 100644 index 5b1de09..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/spi.h +++ /dev/null @@ -1,178 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/spi.h - * @author Marti Bolivar , - * F3-port by Hanspeter Portner - * @brief STM32F3 SPI/I2S series header. - */ - -#ifndef _LIBMAPLE_STM32F3_SPI_H_ -#define _LIBMAPLE_STM32F3_SPI_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Register map base pointers - */ - -struct spi_reg_map; - -#define SPI1_BASE ((struct spi_reg_map*)0x40013000) -#define SPI2_BASE ((struct spi_reg_map*)0x40003800) -#define SPI3_BASE ((struct spi_reg_map*)0x40003C00) - -/* - * F3 additional registry items - */ - -/* Control register 1 */ -/* CRC length bitfield in F3 overwrites the data length field in F1/F2 */ -#define SPI_CR1_CRCL_BIT 11 - -#define SPI_CR1_CRCL (1U << SPI_CR1_CRCL_BIT) - -/* Control register 2 */ -#define SPI_CR2_LDMA_TX_BIT 14 -#define SPI_CR2_LDMA_RX_BIT 13 -#define SPI_CR2_FRXTH_BIT 12 -#define SPI_CR2_DS_SHIFT 8 -#define SPI_CR2_FRF_BIT 4 -#define SPI_CR2_NSSP_BIT 3 - -#define SPI_CR2_LDMA_TX (1U << SPI_CR2_LDMA_TX_BIT) -#define SPI_CR2_LDMA_RX (1U << SPI_CR2_LDMA_RX_BIT) -#define SPI_CR2_FRXTH (1U << SPI_CR2_FRXTH_BIT) -#define SPI_CR2_DS (0x7 << SPI_CR2_DS_SHIFT) -#define SPI_CR2_FRF (1U << SPI_CR2_FRF_BIT) -#define SPI_CR2_NSSP (1U << SPI_CR2_NSSP_BIT) - -/* Status register */ -#define SPI_SR_FTLVL_SHIFT 11 -#define SPI_SR_FRLVL_SHIFT 9 -#define SPI_SR_FRE_BIT 8 - -#define SPI_SR_FTLVL (0x3 << SPI_SR_FTLVL_SHIFT) -#define SPI_SR_FRLVL (0x3 << SPI_SR_FRLVL_SHIFT) -#define SPI_SR_FRE (1U << SPI_SR_FRE_SHIFT) - -/** - * @brief TODO document me - */ -typedef enum spi_crc_size { - SPI_CRC_SIZE_8_BIT = (0x0 << SPI_CR1_CRCL_BIT), - SPI_CRC_SIZE_16_BIT = (0x1 << SPI_CR1_CRCL_BIT), -} spi_crc_size; - -/** - * @brief TODO document me - */ -typedef enum spi_frame_format { - SPI_FRAME_FORMAT_MOTOROLA = (0x0 << SPI_CR2_FRF_BIT), - SPI_FRAME_FORMAT_TI = (0x1 << SPI_CR2_FRF_BIT), -} spi_frame_format; - -/** - * @brief TODO document me - */ -typedef enum spi_ds { - SPI_DATA_SIZE_DEFAULT = (0x0 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_4_BIT = (0x3 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_5_BIT = (0x4 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_6_BIT = (0x5 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_7_BIT = (0x6 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_8_BIT = (0x7 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_9_BIT = (0x8 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_10_BIT = (0x9 << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_11_BIT = (0xA << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_12_BIT = (0xB << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_13_BIT = (0xC << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_14_BIT = (0xD << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_15_BIT = (0xE << SPI_CR2_DS_SHIFT), - SPI_DATA_SIZE_16_BIT = (0xF << SPI_CR2_DS_SHIFT), -} spi_ds; - -/** - * @brief TODO document me - */ -typedef enum spi_fifo_transmission_level { - SPI_FIFO_TRANSMISSION_LEVEL_EMPTY = (0x0 << SPI_SR_FTLVL_SHIFT), - SPI_FIFO_TRANSMISSION_LEVEL_QUARTER = (0x1 << SPI_SR_FTLVL_SHIFT), - SPI_FIFO_TRANSMISSION_LEVEL_HALF = (0x2 << SPI_SR_FTLVL_SHIFT), - SPI_FIFO_TRANSMISSION_LEVEL_FULL = (0x3 << SPI_SR_FTLVL_SHIFT), -} spi_fifo_transmission_level; - -/** - * @brief TODO document me - */ -typedef enum spi_fifo_reception_level { - SPI_FIFO_RECEPTION_LEVEL_EMPTY = (0x0 << SPI_SR_FRLVL_SHIFT), - SPI_FIFO_RECEPTION_LEVEL_QUARTER = (0x1 << SPI_SR_FRLVL_SHIFT), - SPI_FIFO_RECEPTION_LEVEL_HALF = (0x2 << SPI_SR_FRLVL_SHIFT), - SPI_FIFO_RECEPTION_LEVEL_FULL = (0x3 << SPI_SR_FRLVL_SHIFT), -} spi_fifo_reception_level; - -/* - * Device pointers - */ - -struct spi_dev; - -extern struct spi_dev *SPI1; -extern struct spi_dev *SPI2; -extern struct spi_dev *SPI3; - -/* - * Routines - */ - -struct gpio_dev; -extern void spi_config_gpios(struct spi_dev*, uint8, - struct gpio_dev*, uint8, - struct gpio_dev*, uint8, uint8, uint8); - -/** - * @brief Set the data size of the given SPI device. - * - * @param dev SPI device - * @param ds SPI data size - * @see spi_ds - * @see spi_reconfigure() - */ -extern void spi_data_size(struct spi_dev *, spi_ds); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/stm32.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/stm32.h deleted file mode 100644 index c40627c..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/stm32.h +++ /dev/null @@ -1,238 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010, 2011 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f1/include/series/stm32.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 chip- and series-specific definitions. - */ - -#ifndef _LIBMAPLE_STM32F3_H_ -#define _LIBMAPLE_STM32F3_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define __CCM__ __attribute__((section(".CCM"))) - -#define STM32_MCU_SERIES STM32_SERIES_F3 - -/* The STM32F3 series is subdivided into "lines". libmaple currently - * officially supports STM32F303 performance line MCUs (see the - * MCU-specific value section below). - * - * You can use these F3 line defines if porting libmaple to support - * MCUs on other lines. */ -/** STM32F3 302 line (STM32F302 MCUs). */ -#define STM32_F3_LINE_302 0 -/** STM32F3 303 line (STM32F303 MCUs). */ -#define STM32_F3_LINE_303 1 - -/* - * MCU-specific values. - * - * You can use this section to override any of the below settings on a - * per-MCU basis. For example, if your MCU has different STM32_PCLK1 - * or STM32_PCLK2 values, you can set them here and the values for - * STM32F303 microcontrollers set below won't take effect. - */ - -#if defined(MCU_STM32F302CB) -# define STM32_F3_LINE STM32_F3_LINE_302 -# define STM32_NR_GPIO_PORTS 20 -# define STM32_SRAM_END ((void*)0x20008000) -# define STM32_MEDIUM_DENSITY // 48pin package - -#elif defined(MCU_STM32F302RB) -# define STM32_F3_LINE STM32_F3_LINE_302 -# define STM32_NR_GPIO_PORTS 27 -# define STM32_SRAM_END ((void*)0x20008000) -# define STM32_HIGH_DENSITY // 64pin package - -#elif defined(MCU_STM32F302VB) -# define STM32_F3_LINE STM32_F3_LINE_302 -# define STM32_NR_GPIO_PORTS 45 -# define STM32_SRAM_END ((void*)0x20008000) -# define STM32_XL_DENSITY // 100pin package - -#elif defined(MCU_STM32F302CC) -# define STM32_F3_LINE STM32_F3_LINE_302 -# define STM32_NR_GPIO_PORTS 20 -# define STM32_SRAM_END ((void*)0x2000A000) -# define STM32_MEDIUM_DENSITY // 48pin package - -#elif defined(MCU_STM32F302RC) -# define STM32_F3_LINE STM32_F3_LINE_302 -# define STM32_NR_GPIO_PORTS 27 -# define STM32_SRAM_END ((void*)0x2000A000) -# define STM32_HIGH_DENSITY // 64pin package - -#elif defined(MCU_STM32F302VC) -# define STM32_F3_LINE STM32_F3_LINE_302 -# define STM32_NR_GPIO_PORTS 45 -# define STM32_SRAM_END ((void*)0x2000A000) -# define STM32_XL_DENSITY // 100pin package - -#elif defined(MCU_STM32F303CB) -# define STM32_F3_LINE STM32_F3_LINE_303 -# define STM32_NR_GPIO_PORTS 20 -# define STM32_SRAM_END ((void*)0x2000A000) -# define STM32_MEDIUM_DENSITY // 48pin package - -#elif defined(MCU_STM32F303RB) -# define STM32_F3_LINE STM32_F3_LINE_303 -# define STM32_NR_GPIO_PORTS 27 -# define STM32_SRAM_END ((void*)0x2000A000) -# define STM32_HIGH_DENSITY // 64pin package - -#elif defined(MCU_STM32F303VB) -# define STM32_F3_LINE STM32_F3_LINE_303 -# define STM32_NR_GPIO_PORTS 45 -# define STM32_SRAM_END ((void*)0x2000A000) -# define STM32_XL_DENSITY // 100pin package - -#elif defined(MCU_STM32F303CC) -# define STM32_F3_LINE STM32_F3_LINE_303 -# define STM32_NR_GPIO_PORTS 20 -# define STM32_SRAM_END ((void*)0x2000C000) -# define STM32_MEDIUM_DENSITY // 48pin package - -#elif defined(MCU_STM32F303RC) -# define STM32_F3_LINE STM32_F3_LINE_303 -# define STM32_NR_GPIO_PORTS 27 -# define STM32_SRAM_END ((void*)0x2000C000) -# define STM32_HIGH_DENSITY // 64pin package - -#elif defined(MCU_STM32F303VC) -# define STM32_F3_LINE STM32_F3_LINE_303 -# define STM32_NR_GPIO_PORTS 45 -# define STM32_SRAM_END ((void*)0x2000C000) -// # define STM32_XL_DENSITY // 100pin package - -#else -#warning "Unsupported or unspecified STM32F3 MCU." -#endif - -/* - * Derived values. - */ - -#if STM32_F3_LINE == STM32_F3_LINE_302 -# define STM32_HAVE_USB 1 - -# ifdef STM32_MEDIUM_DENSITY -# define STM32_NR_INTERRUPTS 82 -# define STM32_TIMER_MASK 0b111000000001011110 -# define STM32_HAVE_FSMC 0 -# define STM32_HAVE_DAC 1 -# elif defined(STM32_HIGH_DENSITY) -# define STM32_NR_INTERRUPTS 82 -# define STM32_TIMER_MASK 0b111000000001011110 -# define STM32_HAVE_FSMC 0 -# define STM32_HAVE_DAC 1 -# elif defined(STM32_XL_DENSITY) -# define STM32_NR_INTERRUPTS 82 -# define STM32_TIMER_MASK 0b111000000001011110 -# define STM32_HAVE_FSMC 0 -# define STM32_HAVE_DAC 1 -# endif - -#elif STM32_F3_LINE == STM32_F3_LINE_303 -# define STM32_HAVE_USB 1 - -# ifdef STM32_MEDIUM_DENSITY -# define STM32_NR_INTERRUPTS 82 -# define STM32_TIMER_MASK 0b111000000111011110 -# define STM32_HAVE_FSMC 0 -# define STM32_HAVE_DAC 1 -# elif defined(STM32_HIGH_DENSITY) -# define STM32_NR_INTERRUPTS 82 -# define STM32_TIMER_MASK 0b111000000111011110 -# define STM32_HAVE_FSMC 0 -# define STM32_HAVE_DAC 1 -# elif defined(STM32_XL_DENSITY) -# define STM32_NR_INTERRUPTS 82 -# define STM32_TIMER_MASK 0b111000000111011110 -# define STM32_HAVE_FSMC 0 -# define STM32_HAVE_DAC 1 -# endif - -#endif - -/* - * Clock configuration. - * - * You can patch these for your line, MCU, clock configuration, - * etc. here or by setting cflags when compiling libmaple. - */ - -#ifndef STM32_PCLK1 -#define STM32_PCLK1 36000000U -#endif - -#ifndef STM32_PCLK2 -#define STM32_PCLK2 72000000U -#endif - -#ifndef STM32_DELAY_US_MULT -#define STM32_DELAY_US_MULT 12 /* FIXME: value is incorrect. */ -#endif - -/* - * Sanity checks. - * - * Make sure we have the F3-specific defines we need. - * will check that we've defined everything it needs. - */ - -#if !defined(STM32_F3_LINE) -#error "Bad STM32F3 configuration. Check STM32F3 header." -#endif - -/* - * Doxygen - */ - -#ifdef __DOXYGEN__ - -/** - * @brief STM32 line value for the STM32F3 MCU being targeted. - * - * At time of writing, allowed values are: STM32_F3_LINE_303, - * STM32_F3_LINE_302. This set of values may expand as libmaple adds - * support for more STM32F3 lines. - */ -#define STM32_F3_LINE - -#endif /* __DOXYGEN__ */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/syscfg.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/syscfg.h deleted file mode 100644 index 3519e78..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/syscfg.h +++ /dev/null @@ -1,138 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/syscfg.h - * @author F3-port by Hanspeter Portner - * @brief System configuration controller (SYSCFG) - */ - -#ifndef _LIBMAPLE_STM32F3_SYSCFG_H_ -#define _LIBMAPLE_STM32F3_SYSCFG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * Register map and base pointer - */ - -/** - * @brief SYSCFG register map type. - */ -typedef struct syscfg_reg_map { - __io uint32 CFGR1; /**< Configuration register 1*/ - __io uint32 RCR; /**< CCM SRAM protection register */ - __io uint32 EXTICR[4]; /**< External Interrupt configuration register */ - __io uint32 CFGR2; /**< Configuration register 2 */ -} syscfg_reg_map; - -/** SYSCFG register map base pointer */ -#define SYSCFG_BASE ((struct syscfg_reg_map*)0x40010000) - -/* - * Register bit definitions - */ - -/* Configuration register 1 */ - -#define SYSCFG_CFGR1_FPU_IE_SHIFT 26 -#define SYSCFG_CFGR1_ENCODE_MODE_SHIFT 22 -#define SYSCFG_CFGR1_I2C2_FM_PLUS_BIT 21 -#define SYSCFG_CFGR1_I2C1_FM_PLUS_BIT 20 -#define SYSCFG_CFGR1_I2C_PB9_FM_PLUS_BIT 19 -#define SYSCFG_CFGR1_I2C_PB8_FM_PLUS_BIT 18 -#define SYSCFG_CFGR1_I2C_PB7_FM_PLUS_BIT 17 -#define SYSCFG_CFGR1_I2C_PB6_FM_PLUS_BIT 16 -#define SYSCFG_CFGR1_TIM7_DAC2_DMA_RMP_BIT 14 -#define SYSCFG_CFGR1_TIM6_DAC1_DMA_RMP_BIT 13 -#define SYSCFG_CFGR1_TIM17_DMA_RMP_BIT 12 -#define SYSCFG_CFGR1_TIM16_DMA_RMP_BIT 11 -#define SYSCFG_CFGR1_ADC24_DMA_RMP_BIT 8 -#define SYSCFG_CFGR1_DAC_TRIG_RMP_BIT 7 -#define SYSCFG_CFGR1_TIM1_ITR3_RMP_BIT 6 -#define SYSCFG_CFGR1_USB_IT_RMP_BIT 5 - -//FIXME FPU_IE -//FIXME ENCODE_MODE -#define SYSCFG_CFGR1_I2C2_FM_PLUS (1U << SYSCFG_CFGR1_I2C2_FM_PLUS_BIT) -#define SYSCFG_CFGR1_I2C1_FM_PLUS (1U << SYSCFG_CFGR1_I2C1_FM_PLUS_BIT) -#define SYSCFG_CFGR1_I2C1_PB9_FM_PLUS (1U << SYSCFG_CFGR1_I2C1_PB9_FM_PLUS_BIT) -#define SYSCFG_CFGR1_I2C1_PB8_FM_PLUS (1U << SYSCFG_CFGR1_I2C1_PB8_FM_PLUS_BIT) -#define SYSCFG_CFGR1_I2C1_PB7_FM_PLUS (1U << SYSCFG_CFGR1_I2C1_PB7_FM_PLUS_BIT) -#define SYSCFG_CFGR1_I2C1_PB6_FM_PLUS (1U << SYSCFG_CFGR1_I2C1_PB6_FM_PLUS_BIT) -#define SYSCFG_CFGR1_TIM7_DAC2_DMA_RMP (1U << SYSCFG_CFGR1_TIM7_DAC2_DMA_RMP_BIT) -#define SYSCFG_CFGR1_TIM6_DAC1_DMA_RMP (1U << SYSCFG_CFGR1_TIM6_DAC1_DMA_RMP_BIT) -#define SYSCFG_CFGR1_TIM17_DMA_RMP (1U << SYSCFG_CFGR1_TIM17_DMA_RMP_BIT) -#define SYSCFG_CFGR1_TIM16_DMA_RMP (1U << SYSCFG_CFGR1_TIM16_DMA_RMP_BIT) -#define SYSCFG_CFGR1_ADC23_DMA_RMP (1U << SYSCFG_CFGR1_ADC23_DMA_RMP_BIT) -#define SYSCFG_CFGR1_DAC_TRIG_RMP (1U << SYSCFG_CFGR1_DAC_TRIG_RMP_BIT) -#define SYSCFG_CFGR1_TIM1_ITR3_RMP (1U << SYSCFG_CFGR1_TIM1_ITR3_RMP_BIT) -#define SYSCFG_CFGR1_USB_IT_RMP (1U << SYSCFG_CFGR1_USB_IT_RMP_BIT) -#define SYSCFG_CFGR1_MEM_MODE 0X3 - -/* CCM SRAM protection register */ - -#define SYSCFG_RCR_PAGE7_WP_BIT 7 -#define SYSCFG_RCR_PAGE6_WP_BIT 6 -#define SYSCFG_RCR_PAGE5_WP_BIT 5 -#define SYSCFG_RCR_PAGE4_WP_BIT 4 -#define SYSCFG_RCR_PAGE3_WP_BIT 3 -#define SYSCFG_RCR_PAGE2_WP_BIT 2 -#define SYSCFG_RCR_PAGE1_WP_BIT 1 -#define SYSCFG_RCR_PAGE0_WP_BIT 0 - -#define SYSCFG_RCR_PAGE_7 (1U << SYSCFG_RCR_PAGE7_WP_BIT) -#define SYSCFG_RCR_PAGE_6 (1U << SYSCFG_RCR_PAGE6_WP_BIT) -#define SYSCFG_RCR_PAGE_5 (1U << SYSCFG_RCR_PAGE5_WP_BIT) -#define SYSCFG_RCR_PAGE_4 (1U << SYSCFG_RCR_PAGE4_WP_BIT) -#define SYSCFG_RCR_PAGE_3 (1U << SYSCFG_RCR_PAGE3_WP_BIT) -#define SYSCFG_RCR_PAGE_2 (1U << SYSCFG_RCR_PAGE2_WP_BIT) -#define SYSCFG_RCR_PAGE_1 (1U << SYSCFG_RCR_PAGE1_WP_BIT) -#define SYSCFG_RCR_PAGE_0 (1U << SYSCFG_RCR_PAGE0_WP_BIT) - -/* Configuration register 2 */ - -#define SYSCFG_CFGR2_SRAM_PEF_BIT 8 -#define SYSCFG_CFGR2_BYP_ADDR_PAR_BIT 4 -#define SYSCFG_CFGR2_PVD_LOCK_BIT 2 -#define SYSCFG_CFGR2_SRAM_PARITY_LOCK_BIT 1 -#define SYSCFG_CFGR2_LOCKUP_LOCK_BIT 0 - -#define SYSCFG_CFGR2_SRAM_PEF (1U << SYSCFG_CFGR2_SRAM_PEF_BIT) -#define SYSCFG_CFGR2_BYP_ADDR_PAR (1U << SYSCFG_CFGR2_BYP_ADDR_PAR_BIT) -#define SYSCFG_CFGR2_PVD_LOCK (1U << SYSCFG_CFGR2_PVD_LOCK_BIT) -#define SYSCFG_CFGR2_SRAM_PARITY_LOCK (1U << SYSCFG_CFGR2_SRAM_PARITY_LOCK_BIT) -#define SYSCFG_CFGR2_LOCKUP_LOCK (1U << SYSCFG_CFGR2_LOCKUP_LOCK_BIT) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/timer.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/timer.h deleted file mode 100644 index fe13e4c..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/timer.h +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/timer.h - * @author Marti Bolivar , - * F3-port by Hanspeter Portner - * @brief STM32F3 timer support. - */ - -#ifndef _LIBMAPLE_STM32F3_TIMER_H_ -#define _LIBMAPLE_STM32F3_TIMER_H_ - -#include -#include - -/* - * Register maps and base pointers - */ - -/** STM32F1 general purpose timer register map type */ -typedef struct timer_gen_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ - const uint32 RESERVED1; /**< Reserved */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ - const uint32 RESERVED2; /**< Reserved */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ -} timer_gen_reg_map; - -struct timer_adv_reg_map; -struct timer_bas_reg_map; - -/** Timer 1 register map base pointer */ -#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40012C00) -/** Timer 2 register map base pointer */ -#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000) -/** Timer 3 register map base pointer */ -#define TIMER3_BASE ((struct timer_gen_reg_map*)0x40000400) -/** Timer 4 register map base pointer */ -#define TIMER4_BASE ((struct timer_gen_reg_map*)0x40000800) - -/** Timer 6 register map base pointer */ -#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000) -/** Timer 7 register map base pointer */ -#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400) -/** Timer 8 register map base pointer */ -#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40013400) - -/** Timer 15 register map base pointer */ -#define TIMER15_BASE ((struct timer_gen_reg_map*)0x40014000) -/** Timer 16 register map base pointer */ -#define TIMER16_BASE ((struct timer_gen_reg_map*)0x40014400) -/** Timer 17 register map base pointer */ -#define TIMER17_BASE ((struct timer_gen_reg_map*)0x40014800) - -/* - * Device pointers - * - * We only declare device pointers to timers which actually exist on - * the target MCU. - */ - -struct timer_dev; - -extern struct timer_dev *TIMER1; -extern struct timer_dev *TIMER2; /* FIXME 32bit-capable counter */ -extern struct timer_dev *TIMER3; -extern struct timer_dev *TIMER4; -extern struct timer_dev *TIMER6; -#if STM32_F3_LINE == STM32_F3_LINE_303 -extern struct timer_dev *TIMER7; -extern struct timer_dev *TIMER8; -#endif -extern struct timer_dev *TIMER15; -extern struct timer_dev *TIMER16; -extern struct timer_dev *TIMER17; - -/* - * Routines - */ - -gpio_af timer_get_af(struct timer_dev *dev); - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/include/series/usart.h b/STM32F3/cores/maple/libmaple/stm32f3/include/series/usart.h deleted file mode 100644 index d7edcb6..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/include/series/usart.h +++ /dev/null @@ -1,277 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f3/include/series/usart.h - * @author F3-port by Hanspeter Portner - * @brief STM32F3 USART support. - */ - -#ifndef _LIBMAPLE_STM32F3_USART_H_ -#define _LIBMAPLE_STM32F3_USART_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include /* for gpio_af */ - -/* - * Register maps - */ - -/** USART register map type */ -typedef struct usart_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 CR3; /**< Control register 3 */ - __io uint32 BRR; /**< Baud rate register */ - __io uint32 GTPR; /**< Guard time and prescaler register */ - __io uint32 RTOR; /**< Receiver timeout register */ - __io uint32 RQR; /**< Request register */ - __io uint32 SR; /**< ISR Interrupt and status register */ - __io uint32 ICR; /**< Interrupt clear register */ - __io uint16 RDR; /**< Receive data register */ - uint16 RESERVED1; - __io uint16 TDR; /**< Transmit data register */ - uint16 RESERVED2; -} usart_reg_map; - -/* - * Register map base pointers - */ - -/** USART1 register map base pointer */ -#define USART1_BASE ((struct usart_reg_map*)0x40013800) -/** USART2 register map base pointer */ -#define USART2_BASE ((struct usart_reg_map*)0x40004400) -/** USART3 register map base pointer */ -#define USART3_BASE ((struct usart_reg_map*)0x40004800) - -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -/** UART4 register map base pointer */ -#define UART4_BASE ((struct usart_reg_map*)0x40004C00) -/** UART5 register map base pointer */ -#define UART5_BASE ((struct usart_reg_map*)0x40005000) -#endif - -/* - * Devices - */ - -struct usart_dev; -extern struct usart_dev *USART1; -extern struct usart_dev *USART2; -extern struct usart_dev *USART3; -#ifdef STM32_HIGH_DENSITY -extern struct usart_dev *UART4; -extern struct usart_dev *UART5; -#endif - -/* - * F3-only register bit definitions. - */ - -/* Control register 1 */ -#define USART_CR1_EOBIE_BIT 27 -#define USART_CR1_RTOIE_BIT 26 -#define USART_CR1_DEAT4_BIT 25 -#define USART_CR1_DEAT3_BIT 24 -#define USART_CR1_DEAT2_BIT 23 -#define USART_CR1_DEAT1_BIT 22 -#define USART_CR1_DEAT0_BIT 21 -#define USART_CR1_DEDT4_BIT 20 -#define USART_CR1_DEDT3_BIT 19 -#define USART_CR1_DEDT2_BIT 18 -#define USART_CR1_DEDT1_BIT 17 -#define USART_CR1_DEDT0_BIT 16 -#define USART_CR1_OVER8_BIT 15 -#define USART_CR1_CMIE_BIT 14 -#define USART_CR1_MME_BIT 13 -#define USART_CR1_UESM_BIT 1 -#define USART_CR1_UE_BIT 0 - -#define USART_CR1_EOBIE (1UL << USART_CR1_EOBIE_BIT) -#define USART_CR1_RTOIE (1UL << USART_CR1_RTOIE_BIT) -#define USART_CR1_DEAT4 (1UL << USART_CR1_DEAT4_BIT) -#define USART_CR1_DEAT3 (1UL << USART_CR1_DEAT3_BIT) -#define USART_CR1_DEAT2 (1UL << USART_CR1_DEAT2_BIT) -#define USART_CR1_DEAT1 (1UL << USART_CR1_DEAT1_BIT) -#define USART_CR1_DEAT0 (1UL << USART_CR1_DEAT0_BIT) -#define USART_CR1_DEDT4 (1UL << USART_CR1_DEDT4_BIT) -#define USART_CR1_DEDT3 (1UL << USART_CR1_DEDT3_BIT) -#define USART_CR1_DEDT2 (1UL << USART_CR1_DEDT2_BIT) -#define USART_CR1_DEDT1 (1UL << USART_CR1_DEDT1_BIT) -#define USART_CR1_DEDT0 (1UL << USART_CR1_DEDT0_BIT) -#define USART_CR1_OVER8 (1UL << USART_CR1_OVER8_BIT) -#define USART_CR1_CMIE (1UL << USART_CR1_CMIE_BIT) -#define USART_CR1_MME (1UL << USART_CR1_MME_BIT) -#define USART_CR1_UESM (1UL << USART_CR1_UESM_BIT) -#define USART_CR1_UE (1UL << USART_CR1_UE_BIT) - -/* Control register 2 */ -#define USART_CR2_ADD_SHIFT 24 -#define USART_CR2_RTOEN_BIT 23 -#define USART_CR2_ABRMOD1_BIT 22 -#define USART_CR2_ABRMOD0_BIT 21 -#define USART_CR2_ABREN_BIT 20 -#define USART_CR2_MSBFIRST_BIT 19 -#define USART_CR2_DATAINV_BIT 18 -#define USART_CR2_TXINV_BIT 17 -#define USART_CR2_RXINV_BIT 16 -#define USART_CR2_SWAP_BIT 15 -#define USART_CR2_ADDM7_BIT 4 - -#define USART_CR2_ADD (0xFF << USART_CR2_ADD_SHIFT) -#define USART_CR2_RTOEN (1UL << USART_CR2_RTOEN_BIT) -#define USART_CR2_ABRMOD1 (1UL << USART_CR2_ABRMOD1_BIT) -#define USART_CR2_ABRMOD0 (1UL << USART_CR2_ABRMOD0_BIT) -#define USART_CR2_ABREN (1UL << USART_CR2_ABREN_BIT) -#define USART_CR2_MSBFIRST (1UL << USART_CR2_MSBFIRST_BIT) -#define USART_CR2_DATAINV (1UL << USART_CR2_DATAINV_BIT) -#define USART_CR2_TXINV (1UL << USART_CR2_TXINV_BIT) -#define USART_CR2_RXINV (1UL << USART_CR2_RXINV_BIT) -#define USART_CR2_SWAP (1UL << USART_CR2_SWAP_BIT) -#define USART_CR2_ADDM7 (1UL << USART_CR2_ADDM7_BIT) - -/* Control register 3 */ -#define USART_CR3_WUFIE_BIT 22 -#define USART_CR3_WUS_SHIFT 20 -#define USART_CR3_SCAR_SHIFT 17 -#define USART_CR3_DEP_BIT 15 -#define USART_CR3_DEM_BIT 14 -#define USART_CR3_DDRE_BIT 13 -#define USART_CR3_OVRDIS_BIT 12 -#define USART_CR3_ONEBIT_BIT 11 - -#define USART_CR3_WUFIE (1UL << USART_CR3_WUFIE_BIT) -#define USART_CR3_WUS (0x3 << USART_CR3_WUS_SHIFT) -#define USART_CR3_SCAR (0x7 << USART_CR3_SCAR_SHIFT) -#define USART_CR3_DEP (1UL << USART_CR3_DEP_BIT) -#define USART_CR3_DEM (1UL << USART_CR3_DEM_BIT) -#define USART_CR3_DDRE (1UL << USART_CR3_DDRE_BIT) -#define USART_CR3_OVRDIS (1UL << USART_CR3_OVRDIS_BIT) -#define USART_CR3_ONEBIT (1UL << USART_CR3_ONEBIT_BIT) - -/* Receive timeout register */ -#define USART_RTOR_BLEN_SHIFT 24 -#define USART_RTOR_RTO_SHIFT 0 - -#define USART_RTOR_BLEN (0xF << USART_RTOR_BLEN_SHIFT) -#define USART_RTOR_RTO (0xFFF << USART_RTOR_RTO_SHIFT) - -/* Request register */ -#define USART_RQR_TXFRQ_BIT 4 -#define USART_RQR_RXFRQ_BIT 3 -#define USART_RQR_MMRQ_BIT 2 -#define USART_RQR_SBKRQ_BIT 1 -#define USART_RQR_ABRRQ_BIT 0 - -#define USART_RQR_TXFRQ (1UL << USART_RQR_TXFRQ_BIT) -#define USART_RQR_RXFRQ (1UL << USART_RQR_RXFRQ_BIT) -#define USART_RQR_MMRQ (1UL << USART_RQR_MMRQ_BIT) -#define USART_RQR_SBKRQ (1UL << USART_RQR_SBKRQ_BIT) -#define USART_RQR_ABRRQ (1UL << USART_RQR_ABRRQ_BIT) - -/* Interrupt and status register */ -// common register bits with other STM32 series are defined as USART_SR_* for compatibility -#define USART_SR_REACK_BIT 22 -#define USART_SR_TEACK_BIT 21 -#define USART_SR_WUF_BIT 20 -#define USART_SR_RWU_BIT 19 -#define USART_SR_SBKF_BIT 18 -#define USART_SR_CMF_BIT 17 -#define USART_SR_BUSY_BIT 16 -#define USART_SR_ABRF_BIT 15 -#define USART_SR_ABRE_BIT 14 -#define USART_SR_EOBF_BIT 12 -#define USART_SR_RTOF_BIT 11 -#define USART_SR_CTS_BIT 10 -#define USART_SR_CTSIF_BIT 9 - -#define USART_SR_REACK (1UL << USART_ISR_REACK_BIT) -#define USART_SR_TEACK (1UL << USART_ISR_TEACK_BIT) -#define USART_SR_WUF (1UL << USART_ISR_WUF_BIT) -#define USART_SR_RWU (1UL << USART_ISR_RWU_BIT) -#define USART_SR_SBKF (1UL << USART_ISR_SBKF_BIT) -#define USART_SR_CMF (1UL << USART_ISR_CMF_BIT) -#define USART_SR_BUSY (1UL << USART_ISR_BUSY_BIT) -#define USART_SR_ABRF (1UL << USART_ISR_ABRF_BIT) -#define USART_SR_ABRE (1UL << USART_ISR_ABRE_BIT) -#define USART_SR_EOBF (1UL << USART_ISR_EOBF_BIT) -#define USART_SR_RTOF (1UL << USART_ISR_RTOF_BIT) -#define USART_SR_CTS (1UL << USART_ISR_CTS_BIT) -#define USART_SR_CTSIF (1UL << USART_ISR_CTSIF_BIT) - -/* Interrupt clear register */ -#define USART_ICR_WUFCF_BIT 20 -#define USART_ICR_CMCF_BIT 17 -#define USART_ICR_EOBCF_BIT 12 -#define USART_ICR_RTOCF_BIT 11 -#define USART_ICR_CTSCF_BIT 9 -#define USART_ICR_LBDCF_BIT 8 -#define USART_ICR_TCCF_BIT 6 -#define USART_ICR_IDLECF_BIT 4 -#define USART_ICR_ORECF_BIT 3 -#define USART_ICR_NCF_BIT 2 -#define USART_ICR_FECF_BIT 1 -#define USART_ICR_PECF_BIT 0 - -#define USART_ICR_WUFCF (1UL << USART_ICR_WUFCF_BIT) -#define USART_ICR_CMCF (1UL << USART_ICR_CMCF_BIT) -#define USART_ICR_EOBCF (1UL << USART_ICR_EOBCF_BIT) -#define USART_ICR_RTOCF (1UL << USART_ICR_RTOCF_BIT) -#define USART_ICR_CTSCF (1UL << USART_ICR_CTSCF_BIT) -#define USART_ICR_LBDCF (1UL << USART_ICR_LBDCF_BIT) -#define USART_ICR_TCCF (1UL << USART_ICR_TCCF_BIT) -#define USART_ICR_IDLECF (1UL << USART_ICR_IDLECF_BIT) -#define USART_ICR_ORECF (1UL << USART_ICR_ORECF_BIT) -#define USART_ICR_NCF (1UL << USART_ICR_NCF_BIT) -#define USART_ICR_FECF (1UL << USART_ICR_FECF_BIT) -#define USART_ICR_PECF (1UL << USART_ICR_PECF_BIT) - -/* Receive data register */ -#define USART_RDR_RDR_SHIFT 0 - -#define USART_RDR_RDR (0x1FF << USART_RDR_RDR_SHIFT) - - -/* Transmit data register */ -#define USART_TDR_TDR_SHIFT 0 - -#define USART_TDR_TDR (0x1FF << USART_TDR_TDR_SHIFT) - -/* - * Routines - */ - -gpio_af usart_get_af(struct usart_dev *dev); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/STM32F3/cores/maple/libmaple/stm32f3/rules.mk b/STM32F3/cores/maple/libmaple/stm32f3/rules.mk deleted file mode 100644 index f17f745..0000000 --- a/STM32F3/cores/maple/libmaple/stm32f3/rules.mk +++ /dev/null @@ -1,48 +0,0 @@ -# Standard things -sp := $(sp).x -dirstack_$(sp) := $(d) -d := $(dir) -BUILDDIRS += $(BUILD_PATH)/$(d) - -# Local flags -CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror -ASFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror - -# Extra BUILDDIRS -BUILDDIRS += $(BUILD_PATH)/$(d)/F30xxx - -# Local rules and targets -sSRCS_$(d) := F30xxx/isrs.S -sSRCS_$(d) += F30xxx/vector_table.S - -cSRCS_$(d) := adc.c -cSRCS_$(d) += dma.c -cSRCS_$(d) += exti.c -cSRCS_$(d) += gpio.c -cSRCS_$(d) += i2c.c -cSRCS_$(d) += rcc.c -cSRCS_$(d) += spi.c -cSRCS_$(d) += timer.c -cSRCS_$(d) += usart.c -cSRCS_$(d) += syscfg.c -cSRCS_$(d) += fpu.c -cSRCS_$(d) += comp.c -cSRCS_$(d) += opamp.c -cSRCS_$(d) += bkp.c - -sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) -cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) - -OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ - $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) -DEPS_$(d) := $(OBJS_$(d):%.o=%.d) - -$(OBJS_$(d)): TGT_ASFLAGS := $(ASFLAGS_$(d)) -$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) - -TGT_BIN += $(OBJS_$(d)) - -# Standard things --include $(DEPS_$(d)) -d := $(dirstack_$(sp)) -sp := $(basename $(sp)) diff --git a/STM32F3/cores/maple/libmaple/syscfg.c b/STM32F3/cores/maple/libmaple/syscfg.c deleted file mode 100644 index 8b3c963..0000000 --- a/STM32F3/cores/maple/libmaple/syscfg.c +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/syscfg.c - * @brief System configuration controller (SYSCFG) - * @author F3-port by Hanspeter Portner - * - * Availability: STM32F2, STM32F3, STM32F4. - */ - -#include -#include - -void syscfg_init(void) { - rcc_clk_enable(RCC_SYSCFG); - rcc_reset_dev(RCC_SYSCFG); -} diff --git a/STM32F3/cores/maple/libmaple/systick.c b/STM32F3/cores/maple/libmaple/systick.c deleted file mode 100644 index 7568abe..0000000 --- a/STM32F3/cores/maple/libmaple/systick.c +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2010, 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/systick.c - * @brief System timer (SysTick). - */ - -#include - -volatile uint32 systick_uptime_millis; -static void (*systick_user_callback)(void); - -/** - * @brief Initialize and enable SysTick. - * - * Clocks the system timer with the core clock, turns it on, and - * enables interrupts. - * - * @param reload_val Appropriate reload counter to tick every 1 ms. - */ -void systick_init(uint32 reload_val) { - SYSTICK_BASE->RVR = reload_val; - systick_enable(); -} - -/** - * Clock the system timer with the core clock, but don't turn it - * on or enable interrupt. - */ -void systick_disable() { - SYSTICK_BASE->CSR = SYSTICK_CSR_CLKSOURCE_CORE; -} - -/** - * Clock the system timer with the core clock and turn it on; - * interrupt every 1 ms, for systick_timer_millis. - */ -void systick_enable() { - /* re-enables init registers without changing reload val */ - SYSTICK_BASE->CSR = (SYSTICK_CSR_CLKSOURCE_CORE | - SYSTICK_CSR_ENABLE | - SYSTICK_CSR_TICKINT_PEND); -} - -/** - * @brief Attach a callback to be called from the SysTick exception handler. - * - * To detach a callback, call this function again with a null argument. - */ -void systick_attach_callback(void (*callback)(void)) { - systick_user_callback = callback; -} - -/* - * SysTick ISR - */ - -void __exc_systick(void) { - systick_uptime_millis++; - if (systick_user_callback) { - systick_user_callback(); - } -} diff --git a/STM32F3/cores/maple/libmaple/timer.c b/STM32F3/cores/maple/libmaple/timer.c deleted file mode 100644 index e48cb1a..0000000 --- a/STM32F3/cores/maple/libmaple/timer.c +++ /dev/null @@ -1,456 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/timer.c - * @author Marti Bolivar - * @brief Portable timer routines. - */ - -#include -#include -#include "timer_private.h" - -static void disable_channel(timer_dev *dev, uint8 channel); -static void pwm_mode(timer_dev *dev, uint8 channel); -static void output_compare_mode(timer_dev *dev, uint8 channel); - -static inline void enable_irq(timer_dev *dev, uint8 interrupt); - -/* - * Devices - * - * Defer to the timer_private API for declaring these. - */ - -#if STM32_HAVE_TIMER(1) -static timer_dev timer1 = ADVANCED_TIMER(1); -/** Timer 1 device (advanced) */ -timer_dev *TIMER1 = &timer1; -#endif -#if STM32_HAVE_TIMER(2) -static timer_dev timer2 = GENERAL_TIMER(2); -/** Timer 2 device (general-purpose) */ -timer_dev *TIMER2 = &timer2; -#endif -#if STM32_HAVE_TIMER(3) -static timer_dev timer3 = GENERAL_TIMER(3); -/** Timer 3 device (general-purpose) */ -timer_dev *TIMER3 = &timer3; -#endif -#if STM32_HAVE_TIMER(4) -static timer_dev timer4 = GENERAL_TIMER(4); -/** Timer 4 device (general-purpose) */ -timer_dev *TIMER4 = &timer4; -#endif -#if STM32_HAVE_TIMER(5) -static timer_dev timer5 = GENERAL_TIMER(5); -/** Timer 5 device (general-purpose) */ -timer_dev *TIMER5 = &timer5; -#endif -#if STM32_HAVE_TIMER(6) -static timer_dev timer6 = BASIC_TIMER(6); -/** Timer 6 device (basic) */ -timer_dev *TIMER6 = &timer6; -#endif -#if STM32_HAVE_TIMER(7) -static timer_dev timer7 = BASIC_TIMER(7); -/** Timer 7 device (basic) */ -timer_dev *TIMER7 = &timer7; -#endif -#if STM32_HAVE_TIMER(8) -static timer_dev timer8 = ADVANCED_TIMER(8); -/** Timer 8 device (advanced) */ -timer_dev *TIMER8 = &timer8; -#endif -#if STM32_HAVE_TIMER(9) -static timer_dev timer9 = RESTRICTED_GENERAL_TIMER(9, TIMER_DIER_TIE_BIT); -/** Timer 9 device (general-purpose) */ -timer_dev *TIMER9 = &timer9; -#endif -#if STM32_HAVE_TIMER(10) -static timer_dev timer10 = RESTRICTED_GENERAL_TIMER(10, TIMER_DIER_CC1IE_BIT); -/** Timer 10 device (general-purpose) */ -timer_dev *TIMER10 = &timer10; -#endif -#if STM32_HAVE_TIMER(11) -static timer_dev timer11 = RESTRICTED_GENERAL_TIMER(11, TIMER_DIER_CC1IE_BIT); -/** Timer 11 device (general-purpose) */ -timer_dev *TIMER11 = &timer11; -#endif -#if STM32_HAVE_TIMER(12) -static timer_dev timer12 = RESTRICTED_GENERAL_TIMER(12, TIMER_DIER_TIE_BIT); -/** Timer 12 device (general-purpose) */ -timer_dev *TIMER12 = &timer12; -#endif -#if STM32_HAVE_TIMER(13) -static timer_dev timer13 = RESTRICTED_GENERAL_TIMER(13, TIMER_DIER_CC1IE_BIT); -/** Timer 13 device (general-purpose) */ -timer_dev *TIMER13 = &timer13; -#endif -#if STM32_HAVE_TIMER(14) -static timer_dev timer14 = RESTRICTED_GENERAL_TIMER(14, TIMER_DIER_CC1IE_BIT); -/** Timer 14 device (general-purpose) */ -timer_dev *TIMER14 = &timer14; -#endif -#if STM32_HAVE_TIMER(15) -static timer_dev timer15 = RESTRICTED_GENERAL_TIMER(15, TIMER_DIER_TIE_BIT); //XXX -/** Timer 15 device (general-purpose) */ -timer_dev *TIMER15 = &timer15; -#endif -#if STM32_HAVE_TIMER(16) -static timer_dev timer16 = RESTRICTED_GENERAL_TIMER(16, TIMER_DIER_CC1IE_BIT); //XXX -/** Timer 16 device (general-purpose) */ -timer_dev *TIMER16 = &timer16; -#endif -#if STM32_HAVE_TIMER(17) -static timer_dev timer17 = RESTRICTED_GENERAL_TIMER(17, TIMER_DIER_CC1IE_BIT); //XXX -/** Timer 17 device (general-purpose) */ -timer_dev *TIMER17 = &timer17; -#endif - -/* - * Routines - */ - -/** - * @brief Call a function on timer devices. - * @param fn Function to call on each timer device. - */ -void timer_foreach(void (*fn)(timer_dev*)) { -#if STM32_HAVE_TIMER(1) - fn(TIMER1); -#endif -#if STM32_HAVE_TIMER(2) - fn(TIMER2); -#endif -#if STM32_HAVE_TIMER(3) - fn(TIMER3); -#endif -#if STM32_HAVE_TIMER(4) - fn(TIMER4); -#endif -#if STM32_HAVE_TIMER(5) - fn(TIMER5); -#endif -#if STM32_HAVE_TIMER(6) - fn(TIMER6); -#endif -#if STM32_HAVE_TIMER(7) - fn(TIMER7); -#endif -#if STM32_HAVE_TIMER(8) - fn(TIMER8); -#endif -#if STM32_HAVE_TIMER(9) - fn(TIMER9); -#endif -#if STM32_HAVE_TIMER(10) - fn(TIMER10); -#endif -#if STM32_HAVE_TIMER(11) - fn(TIMER11); -#endif -#if STM32_HAVE_TIMER(12) - fn(TIMER12); -#endif -#if STM32_HAVE_TIMER(13) - fn(TIMER13); -#endif -#if STM32_HAVE_TIMER(14) - fn(TIMER14); -#endif -#if STM32_HAVE_TIMER(15) - fn(TIMER15); -#endif -#if STM32_HAVE_TIMER(16) - fn(TIMER16); -#endif -#if STM32_HAVE_TIMER(17) - fn(TIMER17); -#endif -} - -/** - * Initialize a timer, and reset its register map. - * @param dev Timer to initialize - */ -void timer_init(timer_dev *dev) { - rcc_clk_enable(dev->clk_id); - rcc_reset_dev(dev->clk_id); -} - -/** - * @brief Disable a timer. - * - * The timer will stop counting, all DMA requests and interrupts will - * be disabled, and no state changes will be output. - * - * @param dev Timer to disable. - */ -void timer_disable(timer_dev *dev) { - (dev->regs).bas->CR1 = 0; - (dev->regs).bas->DIER = 0; - switch (dev->type) { - case TIMER_ADVANCED: /* fall-through */ - case TIMER_GENERAL: - (dev->regs).gen->CCER = 0; - break; - case TIMER_BASIC: - break; - } -} - -/** - * Sets the mode of an individual timer channel. - * - * Note that not all timers can be configured in every mode. For - * example, basic timers cannot be configured to output compare mode. - * Be sure to use a timer which is appropriate for the mode you want. - * - * @param dev Timer whose channel mode to set - * @param channel Relevant channel - * @param mode New timer mode for channel - */ -void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) { - ASSERT_FAULT(channel > 0 && channel <= 4); - - /* TODO decide about the basic timers */ - ASSERT(dev->type != TIMER_BASIC); - if (dev->type == TIMER_BASIC) - return; - - switch (mode) { - case TIMER_DISABLED: - disable_channel(dev, channel); - break; - case TIMER_PWM: - pwm_mode(dev, channel); - break; - case TIMER_OUTPUT_COMPARE: - output_compare_mode(dev, channel); - break; - } -} - -/** - * @brief Determine whether a timer has a particular capture/compare channel. - * - * Different timers have different numbers of capture/compare channels - * (and some have none at all). Use this function to test whether a - * given timer/channel combination will work. - * - * @param dev Timer device - * @param channel Capture/compare channel, from 1 to 4 - * @return Nonzero if dev has channel, zero otherwise. - */ -int timer_has_cc_channel(timer_dev *dev, uint8 channel) { - /* On all currently supported series: advanced and "full-featured" - * general purpose timers have all four channels. Of the - * restricted general timers, timers 9, 12 and 15 have channels 1 and - * 2; the others have channel 1 only. Basic timers have none. */ - rcc_clk_id id = dev->clk_id; - ASSERT((1 <= channel) && (channel <= 4)); - if (id <= RCC_TIMER5 || id == RCC_TIMER8) { - return 1; /* 1 and 8 are advanced, 2-5 are "full" general */ - } else if (id <= RCC_TIMER7) { - return 0; /* 6 and 7 are basic */ - } - /* The rest are restricted general. */ - return (((id == RCC_TIMER9 || id == RCC_TIMER12 || id == RCC_TIMER15) && channel <= 2) || - channel == 1); -} - -/** - * @brief Attach a timer interrupt. - * @param dev Timer device - * @param interrupt Interrupt number to attach to; this may be any - * timer_interrupt_id or timer_channel value appropriate - * for the timer. - * @param handler Handler to attach to the given interrupt. - * @see timer_interrupt_id - * @see timer_channel - */ -void timer_attach_interrupt(timer_dev *dev, - uint8 interrupt, - voidFuncPtr handler) { - dev->handlers[interrupt] = handler; - timer_enable_irq(dev, interrupt); - enable_irq(dev, interrupt); -} - -/** - * @brief Detach a timer interrupt. - * @param dev Timer device - * @param interrupt Interrupt number to detach; this may be any - * timer_interrupt_id or timer_channel value appropriate - * for the timer. - * @see timer_interrupt_id - * @see timer_channel - */ -void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) { - timer_disable_irq(dev, interrupt); - dev->handlers[interrupt] = NULL; -} - -/* - * Utilities - */ - -static void disable_channel(timer_dev *dev, uint8 channel) { - timer_detach_interrupt(dev, channel); - timer_cc_disable(dev, channel); -} - -static void pwm_mode(timer_dev *dev, uint8 channel) { - timer_disable_irq(dev, channel); - timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); - timer_cc_enable(dev, channel); -} - -static void output_compare_mode(timer_dev *dev, uint8 channel) { - timer_oc_set_mode(dev, channel, TIMER_OC_MODE_ACTIVE_ON_MATCH, 0); - timer_cc_enable(dev, channel); -} - -static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id); -static void enable_bas_gen_irq(timer_dev *dev); - -static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) { - if (dev->type == TIMER_ADVANCED) { - enable_adv_irq(dev, iid); - } else { - enable_bas_gen_irq(dev); - } -} - -/* Advanced control timers have several IRQ lines corresponding to - * different timer interrupts. - * - * Note: This function assumes that the only advanced timers are TIM1 - * and TIM8, and needs the obvious changes if that assumption is - * violated by a later STM32 series. */ -static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id) { - uint8 is_tim1 = dev->clk_id == RCC_TIMER1; - nvic_irq_num irq_num; - switch (id) { - case TIMER_UPDATE_INTERRUPT: - irq_num = (is_tim1 ? - NVIC_TIMER1_UP_TIMER10 : - NVIC_TIMER8_UP_TIMER13); - break; - case TIMER_CC1_INTERRUPT: /* Fall through */ - case TIMER_CC2_INTERRUPT: /* ... */ - case TIMER_CC3_INTERRUPT: /* ... */ - case TIMER_CC4_INTERRUPT: - irq_num = is_tim1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC; - break; - case TIMER_COM_INTERRUPT: /* Fall through */ - case TIMER_TRG_INTERRUPT: - irq_num = (is_tim1 ? - NVIC_TIMER1_TRG_COM_TIMER11 : - NVIC_TIMER8_TRG_COM_TIMER14); - break; - case TIMER_BREAK_INTERRUPT: - irq_num = (is_tim1 ? - NVIC_TIMER1_BRK_TIMER9 : - NVIC_TIMER8_BRK_TIMER12); - break; - default: - /* Can't happen, but placate the compiler */ - ASSERT(0); - return; - } - nvic_irq_enable(irq_num); -} - -/* Basic and general purpose timers have a single IRQ line, which is - * shared by all interrupts supported by a particular timer. */ -static void enable_bas_gen_irq(timer_dev *dev) { - nvic_irq_num irq_num; - switch (dev->clk_id) { - case RCC_TIMER2: - irq_num = NVIC_TIMER2; - break; - case RCC_TIMER3: - irq_num = NVIC_TIMER3; - break; - case RCC_TIMER4: - irq_num = NVIC_TIMER4; - break; -#if STM32_HAVE_TIMER(5) - case RCC_TIMER5: - irq_num = NVIC_TIMER5; - break; -#endif - case RCC_TIMER6: - irq_num = NVIC_TIMER6; - break; - case RCC_TIMER7: - irq_num = NVIC_TIMER7; - break; - case RCC_TIMER9: - irq_num = NVIC_TIMER1_BRK_TIMER9; - break; - case RCC_TIMER10: - irq_num = NVIC_TIMER1_UP_TIMER10; - break; - case RCC_TIMER11: - irq_num = NVIC_TIMER1_TRG_COM_TIMER11; - break; - case RCC_TIMER12: - irq_num = NVIC_TIMER8_BRK_TIMER12; - break; - case RCC_TIMER13: - irq_num = NVIC_TIMER8_UP_TIMER13; - break; - case RCC_TIMER14: - irq_num = NVIC_TIMER8_TRG_COM_TIMER14; - break; -#if STM32_HAVE_TIMER(15) - case RCC_TIMER15: - //irq_num = NVIC_TIMER1_BRK_TIMER15; - irq_num = NVIC_TIMER1_BRK_TIMER9; - break; -#endif -#if STM32_HAVE_TIMER(16) - case RCC_TIMER16: - //irq_num = NVIC_TIMER1_UP_TIMER16; - irq_num = NVIC_TIMER1_UP_TIMER10; - break; -#endif -#if STM32_HAVE_TIMER(17) - case RCC_TIMER17: - //irq_num = NVIC_TIMER1_TRG_COM_TIMER17; - irq_num = NVIC_TIMER1_TRG_COM_TIMER11; - break; -#endif - default: - ASSERT_FAULT(0); - return; - } - nvic_irq_enable(irq_num); -} diff --git a/STM32F3/cores/maple/libmaple/timer_private.h b/STM32F3/cores/maple/libmaple/timer_private.h deleted file mode 100644 index 320c636..0000000 --- a/STM32F3/cores/maple/libmaple/timer_private.h +++ /dev/null @@ -1,235 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/timer_private.h - * @author Marti Bolivar - * @brief Private, internal timer APIs. - */ - -#ifndef _LIBMAPLE_TIMER_PRIVATE_H_ -#define _LIBMAPLE_TIMER_PRIVATE_H_ - -/* - * Helper macros for declaring timer_devs of various timer_types - */ - -/* The indexes of user handlers in a timer_dev.handlers are just like - * the corresponding DIER bits, as follows: */ - -/* Advanced timers: - * [0] = Update handler; - * [1,2,3,4] = capture/compare 1,2,3,4 handlers, respectively; - * [5] = COM; - * [6] = TRG; - * [7] = BRK. */ -#define NR_ADV_HANDLERS 8 -/* General purpose timers: - * [0] = update; - * [1,2,3,4] = capture/compare 1,2,3,4; - * [5] = ; - * [6] = trigger. */ -#define NR_GEN_HANDLERS 7 -/* Basic timers: - * [0] = update. */ -#define NR_BAS_HANDLERS 1 - -/* For declaring advanced timers. */ -#define ADVANCED_TIMER(num) \ - { \ - .regs = { .adv = TIMER##num##_BASE }, \ - .clk_id = RCC_TIMER##num, \ - .type = TIMER_ADVANCED, \ - .handlers = { [NR_ADV_HANDLERS - 1] = 0 }, \ - } - -/* For declaring full-featured general purpose timers. */ -#define GENERAL_TIMER(num) \ - { \ - .regs = { .gen = TIMER##num##_BASE }, \ - .clk_id = RCC_TIMER##num, \ - .type = TIMER_GENERAL, \ - .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, \ - } - -/* For declaring general purpose timers with limited interrupt - * capability (e.g. timers 9 through 14 on STM32F2 and XL-density - * STM32F1). */ -#define RESTRICTED_GENERAL_TIMER(num, max_dier_bit) \ - { \ - .regs = { .gen = TIMER##num##_BASE }, \ - .clk_id = RCC_TIMER##num, \ - .type = TIMER_GENERAL, \ - .handlers = { [max_dier_bit] = 0 }, \ - } - -/* For declaring basic timers (e.g. TIM6 and TIM7). */ -#define BASIC_TIMER(num) \ - { \ - .regs = { .bas = TIMER##num##_BASE }, \ - .clk_id = RCC_TIMER##num, \ - .type = TIMER_BASIC, \ - .handlers = { [NR_BAS_HANDLERS - 1] = 0 }, \ - } - -/* - * IRQ handlers - * - * These decode TIMx_DIER and TIMx_SR, then dispatch to the user-level - * IRQ handlers. They also clean up TIMx_SR afterwards, so the user - * doesn't have to deal with register details. - * - * Notes: - * - * - These dispatch routines make use of the fact that DIER interrupt - * enable bits and SR interrupt flags have common bit positions. - * Thus, ANDing DIER and SR lets us check if an interrupt is enabled - * and if it has occurred simultaneously. - * - * - We force these routines to inline to avoid call overhead, but - * there aren't any measurements to prove that this is actually a - * good idea. Profile-directed optimizations are definitely wanted. */ - -/* A special-case dispatch routine for timers which only serve a - * single interrupt on a given IRQ line. - * - * This function still checks DIER & SR, as in some cases, a timer may - * only serve a single interrupt on a particular NVIC line, but that - * line may be shared with another timer. For example, the timer 1 - * update interrupt shares an IRQ line with the timer 10 interrupt on - * STM32F1 (XL-density), STM32F2, and STM32F4. */ -static __always_inline void dispatch_single_irq(timer_dev *dev, - timer_interrupt_id iid, - uint32 irq_mask) { - timer_bas_reg_map *regs = (dev->regs).bas; - if (regs->DIER & regs->SR & irq_mask) { - void (*handler)(void) = dev->handlers[iid]; - if (handler) { - handler(); - regs->SR &= ~irq_mask; - } - } -} - -/* Helper macro for dispatch routines which service multiple interrupts. */ -#define handle_irq(dier_sr, irq_mask, handlers, iid, handled_irq) do { \ - if ((dier_sr) & (irq_mask)) { \ - void (*__handler)(void) = (handlers)[iid]; \ - if (__handler) { \ - __handler(); \ - handled_irq |= (irq_mask); \ - } \ - } \ - } while (0) - -static __always_inline void dispatch_adv_brk(timer_dev *dev) { - dispatch_single_irq(dev, TIMER_BREAK_INTERRUPT, TIMER_SR_BIF); -} - -static __always_inline void dispatch_adv_up(timer_dev *dev) { - dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); -} - -static __always_inline void dispatch_adv_trg_com(timer_dev *dev) { - timer_adv_reg_map *regs = (dev->regs).adv; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; /* Logical OR of SR interrupt flags we end up - * handling. We clear these. User handlers - * must clear overcapture flags, to avoid - * wasting time in output mode. */ - - handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_COMIF, hs, TIMER_COM_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -static __always_inline void dispatch_adv_cc(timer_dev *dev) { - timer_adv_reg_map *regs = (dev->regs).adv; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; - - handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -static __always_inline void dispatch_general(timer_dev *dev) { - timer_gen_reg_map *regs = (dev->regs).gen; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; - - handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -/* On F1 (XL-density), F2, and F4, TIM9 and TIM12 are restricted - * general-purpose timers with update, CC1, CC2, and TRG interrupts. */ -static __always_inline void dispatch_tim_9_12(timer_dev *dev) { - timer_gen_reg_map *regs = (dev->regs).gen; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; - - handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -/* On F1 (XL-density), F2, and F4, timers 10, 11, 13, and 14 are - * restricted general-purpose timers with update and CC1 interrupts. */ -static __always_inline void dispatch_tim_10_11_13_14(timer_dev *dev) { - timer_gen_reg_map *regs = (dev->regs).gen; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; - - handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -static __always_inline void dispatch_basic(timer_dev *dev) { - dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); -} - -#endif diff --git a/STM32F3/cores/maple/libmaple/usart.c b/STM32F3/cores/maple/libmaple/usart.c deleted file mode 100644 index 52da4d1..0000000 --- a/STM32F3/cores/maple/libmaple/usart.c +++ /dev/null @@ -1,122 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/usart.c - * @author Marti Bolivar , - * Perry Hung - * @brief Portable USART routines - */ - -#include - -/** - * @brief Initialize a serial port. - * @param dev Serial port to be initialized - */ -void usart_init(usart_dev *dev) { - rb_init(dev->rb, USART_RX_BUF_SIZE, dev->rx_buf); - rcc_clk_enable(dev->clk_id); - nvic_irq_enable(dev->irq_num); -} - -/** - * @brief Enable a serial port. - * - * USART is enabled in single buffer transmission mode, multibuffer - * receiver mode, 8n1. - * - * Serial port must have a baud rate configured to work properly. - * - * @param dev Serial port to enable. - * @see usart_set_baud_rate() - */ -void usart_enable(usart_dev *dev) { - usart_reg_map *regs = dev->regs; - regs->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | - USART_CR1_M_8N1); - regs->CR1 |= USART_CR1_UE; -} - -/** - * @brief Turn off a serial port. - * @param dev Serial port to be disabled - */ -void usart_disable(usart_dev *dev) { - /* FIXME this misbehaves (on F1) if you try to use PWM on TX afterwards */ - usart_reg_map *regs = dev->regs; - - /* TC bit must be high before disabling the USART */ - while((regs->CR1 & USART_CR1_UE) && !(regs->SR & USART_SR_TC)) - ; - - /* Disable UE */ - regs->CR1 &= ~USART_CR1_UE; - - /* Clean up buffer */ - usart_reset_rx(dev); -} - -/** - * @brief Nonblocking USART receive. - * @param dev Serial port to receive bytes from - * @param buf Buffer to store received bytes into - * @param len Maximum number of bytes to store - * @return Number of bytes received - */ -uint32 usart_rx(usart_dev *dev, uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (usart_data_available(dev) && rxed < len) { - *buf++ = usart_getc(dev); - rxed++; - } - return rxed; -} - -/** - * @brief Transmit an unsigned integer to the specified serial port in - * decimal format. - * - * This function blocks until the integer's digits have been - * completely transmitted. - * - * @param dev Serial port to send on - * @param val Number to print - */ -void usart_putudec(usart_dev *dev, uint32 val) { - char digits[12]; - int i = 0; - - do { - digits[i++] = val % 10 + '0'; - val /= 10; - } while (val > 0); - - while (--i >= 0) { - usart_putc(dev, digits[i]); - } -} diff --git a/STM32F3/cores/maple/libmaple/usart_private.c b/STM32F3/cores/maple/libmaple/usart_private.c deleted file mode 100644 index 0eaacdf..0000000 --- a/STM32F3/cores/maple/libmaple/usart_private.c +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/usart_private.c - * @author Marti Bolivar - * @brief Private USART routines. - */ - -#include "usart_private.h" -#include -#include - -uint32 _usart_clock_freq(usart_dev *dev) { - rcc_clk_domain domain = rcc_dev_clk(dev->clk_id); - return (domain == RCC_APB1 ? STM32_PCLK1 : - (domain == RCC_APB2 ? STM32_PCLK2 : 0)); -} diff --git a/STM32F3/cores/maple/libmaple/usart_private.h b/STM32F3/cores/maple/libmaple/usart_private.h deleted file mode 100644 index e6044d8..0000000 --- a/STM32F3/cores/maple/libmaple/usart_private.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/usart_private.h - * @author Marti Bolivar - * @brief Private USART header. - */ - -#ifndef _LIBMAPLE_USART_PRIVATE_H_ -#define _LIBMAPLE_USART_PRIVATE_H_ - -#include -#include - -uint32 _usart_clock_freq(usart_dev *dev); - -#endif diff --git a/STM32F3/cores/maple/libmaple/usb/README b/STM32F3/cores/maple/libmaple/usb/README deleted file mode 100644 index d0fca8d..0000000 --- a/STM32F3/cores/maple/libmaple/usb/README +++ /dev/null @@ -1,63 +0,0 @@ -The USB submodule of libmaple is a separate piece of the codebase for -reasons that are largely historical. - -Current Status: - - There's only support for the USB device peripheral found on - STM32F103s. - - We rely on the low level core library provided by ST to implement - the USB transfer protocol for control endpoint transfers. - - The virtual com port (which is exposed via - ) serves two important purposes. - - 1) It allows serial data transfers between user sketches an a - host computer. - - 2) It allows the host PC to issue a system reset into the DFU - bootloader with the DTR + RTS + "1EAF" sequence (see - leaflabs.com/docs/bootloader.html for more information on - this). - - After reset, Maple will run the DFU bootloader for a few seconds, - during which the user can begin a DFU upload operation (uploads - application binary into RAM/FLASH). Thus, without this virtual com - port, it would be necessary to find an alternative means to reset - the chip in order to enable the bootloader. - - If you would like to develop your own USB application for whatever - reason (e.g. to use faster isochronous enpoints for streaming - audio, or implement the USB HID or Mass Storage specs), then - ensure that you leave some hook for resetting Maple remotely in - order to spin up the DFU bootloader. Please make sure to get - yourself a unique vendor/product ID pair for your application, as - some operating systems will assign a host-side driver based on - these tags. - - It would be possible to build a compound USB device, that - implements endpoints for both the virtual COM port as well as some - other components (mass storage etc.). However, this turns out to - be a burden from the host driver side, as Windows and *nix handle - compound USB devices quite differently. - - Be mindful that enabling the USB peripheral isn't "free." The - device must respond to periodic bus activity (every few - milliseconds) by servicing an ISR. Therefore, the USB application - should be disabled inside of timing critical applications. - - In order to disconnect the device from the host, a USB_DISC pin is - asserted (e.g. on Maple, this is PC12). Alternatively, the NVIC - can be directly configured to disable the USB LP/HP IRQ's. - - The files inside of usb_lib were provided by ST and are subject to - their own license, all other files were written by the LeafLabs - team and fall under the MIT license. - -TODO: - - - Generic USB driver core with series-provided backends, like - libopencm3 has. - - Strip out ST code. - - Integration with a high level USB library (like LUFA/MyUSB) to - allow users to write custom USB applications. diff --git a/STM32F3/cores/maple/libmaple/usb/usb.c b/STM32F3/cores/maple/libmaple/usb/usb.c deleted file mode 100644 index f694f04..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb.c +++ /dev/null @@ -1,387 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/usb/stm32f1/usb.c - * @brief USB support. - * - * This is a mess. - */ - -#include - -#include -#include - -/* Private headers */ -#include "usb_reg_map.h" -#include "usb_lib_globals.h" - -/* usb_lib headers */ -#include "usb_type.h" -#include "usb_core.h" - -static void dispatch_ctr_lp(void); - -/* - * usb_lib/ globals - */ - -uint16 SaveTState; /* caches TX status for later use */ -uint16 SaveRState; /* caches RX status for later use */ - -/* - * Other state - */ - -typedef enum { - RESUME_EXTERNAL, - RESUME_INTERNAL, - RESUME_LATER, - RESUME_WAIT, - RESUME_START, - RESUME_ON, - RESUME_OFF, - RESUME_ESOF -} RESUME_STATE; - -struct { - volatile RESUME_STATE eState; - volatile uint8 bESOFcnt; -} ResumeS; - -static usblib_dev usblib = { - .irq_mask = USB_ISR_MSK, - .state = USB_UNCONNECTED, - .prevState = USB_UNCONNECTED, - .clk_id = RCC_USB, -}; -usblib_dev *USBLIB = &usblib; - -/* - * Routines - */ - -void usb_init_usblib(usblib_dev *dev, - void (**ep_int_in)(void), - void (**ep_int_out)(void)) { - rcc_clk_enable(dev->clk_id); - - dev->ep_int_in = ep_int_in; - dev->ep_int_out = ep_int_out; - - /* usb_lib/ declares both and then assumes that pFoo points to Foo - * (even though the names don't always match), which is stupid for - * all of the obvious reasons, but whatever. Here we are. */ - pInformation = &Device_Info; - pProperty = &Device_Property; - pUser_Standard_Requests = &User_Standard_Requests; - - pInformation->ControlState = 2; /* FIXME [0.0.12] use - CONTROL_STATE enumerator */ - pProperty->Init(); -} - -static void usb_suspend(void) { - uint16 cntr; - - /* TODO decide if read/modify/write is really what we want - * (e.g. usb_resume_init() reconfigures CNTR). */ - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_FSUSP; - USB_BASE->CNTR = cntr; - cntr |= USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; - - USBLIB->prevState = USBLIB->state; - USBLIB->state = USB_SUSPENDED; -} - -static void usb_resume_init(void) { - uint16 cntr; - - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; - - /* Enable interrupt lines */ - USB_BASE->CNTR = USB_ISR_MSK; -} - -static void usb_resume(RESUME_STATE eResumeSetVal) { - uint16 cntr; - - if (eResumeSetVal != RESUME_ESOF) { - ResumeS.eState = eResumeSetVal; - } - - switch (ResumeS.eState) { - case RESUME_EXTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_OFF; - USBLIB->state = USBLIB->prevState; - break; - case RESUME_INTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_START; - break; - case RESUME_LATER: - ResumeS.bESOFcnt = 2; - ResumeS.eState = RESUME_WAIT; - break; - case RESUME_WAIT: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) { - ResumeS.eState = RESUME_START; - } - break; - case RESUME_START: - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_ON; - ResumeS.bESOFcnt = 10; - break; - case RESUME_ON: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) { - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - USBLIB->state = USBLIB->prevState; - ResumeS.eState = RESUME_OFF; - } - break; - case RESUME_OFF: - case RESUME_ESOF: - default: - ResumeS.eState = RESUME_OFF; - break; - } -} - -#define SUSPEND_ENABLED 1 -void __irq_usb_lp_can_rx0(void) { - uint16 istr = USB_BASE->ISTR; - - /* Use USB_ISR_MSK to only include code for bits we care about. */ - -#if (USB_ISR_MSK & USB_ISTR_RESET) - if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_RESET; - pProperty->Reset(); - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_PMAOVR) - if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_PMAOVR; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_ERR) - if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ERR; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_WKUP) - if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_WKUP; - usb_resume(RESUME_EXTERNAL); - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_SUSP) - if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { - /* check if SUSPEND is possible */ - if (SUSPEND_ENABLED) { - usb_suspend(); - } else { - /* if not possible then resume after xx ms */ - usb_resume(RESUME_LATER); - } - /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - USB_BASE->ISTR = ~USB_ISTR_SUSP; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_SOF) - if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_SOF; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_ESOF) - if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ESOF; - /* resume handling timing is made with ESOFs */ - usb_resume(RESUME_ESOF); /* request without change of the machine state */ - } -#endif - - /* - * Service the correct transfer interrupt. - */ - -#if (USB_ISR_MSK & USB_ISTR_CTR) - if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { - dispatch_ctr_lp(); - } -#endif -} - -/* - * Auxiliary routines - */ - -static inline uint8 dispatch_endpt_zero(uint16 istr_dir); -static inline void dispatch_endpt(uint8 ep); -static inline void set_rx_tx_status0(uint16 rx, uint16 tx); - -static void handle_setup0(void); -static void handle_in0(void); -static void handle_out0(void); - -static void dispatch_ctr_lp() { - uint16 istr; - while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) { - /* TODO WTF, figure this out: RM0008 says CTR is read-only, - * but ST's firmware claims it's clear-only, and emphasizes - * the importance of clearing it in more than one place. */ - USB_BASE->ISTR = ~USB_ISTR_CTR; - uint8 ep_id = istr & USB_ISTR_EP_ID; - if (ep_id == 0) { - /* TODO figure out why it's OK to break out of the loop - * once we're done serving endpoint zero, but not okay if - * there are multiple nonzero endpoint transfers to - * handle. */ - if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) { - return; - } - } else { - dispatch_endpt(ep_id); - } - } -} - -/* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's - * code, and is ugly/confusing in its use of SaveRState/SaveTState. - * Fixing this requires filling in handle_in0(), handle_setup0(), - * handle_out0(). */ -static inline uint8 dispatch_endpt_zero(uint16 istr_dir) { - uint32 epr = (uint16)USB_BASE->EP[0]; - - if (!(epr & (USB_EP_CTR_TX | USB_EP_SETUP | USB_EP_CTR_RX))) { - return 0; - } - - /* Cache RX/TX statuses in SaveRState/SaveTState, respectively. - * The various handle_foo0() may clobber these values - * before we reset them at the end of this routine. */ - SaveRState = epr & USB_EP_STAT_RX; - SaveTState = epr & USB_EP_STAT_TX; - - /* Set actual RX/TX statuses to NAK while we're thinking */ - set_rx_tx_status0(USB_EP_STAT_RX_NAK, USB_EP_STAT_TX_NAK); - - if (istr_dir == 0) { - /* ST RM0008: "If DIR bit=0, CTR_TX bit is set in the USB_EPnR - * register related to the interrupting endpoint. The - * interrupting transaction is of IN type (data transmitted by - * the USB peripheral to the host PC)." */ - ASSERT_FAULT(epr & USB_EP_CTR_TX); - usb_clear_ctr_tx(USB_EP0); - handle_in0(); - } else { - /* RM0008: "If DIR bit=1, CTR_RX bit or both CTR_TX/CTR_RX - * are set in the USB_EPnR register related to the - * interrupting endpoint. The interrupting transaction is of - * OUT type (data received by the USB peripheral from the host - * PC) or two pending transactions are waiting to be - * processed." - * - * [mbolivar] Note how the following control flow (which - * replicates ST's) doesn't seem to actually handle both - * interrupts that are ostensibly pending when both CTR_RX and - * CTR_TX are set. - * - * TODO sort this mess out. - */ - if (epr & USB_EP_CTR_TX) { - usb_clear_ctr_tx(USB_EP0); - handle_in0(); - } else { /* SETUP or CTR_RX */ - /* SETUP is held constant while CTR_RX is set, so clear it - * either way */ - usb_clear_ctr_rx(USB_EP0); - if (epr & USB_EP_SETUP) { - handle_setup0(); - } else { /* CTR_RX */ - handle_out0(); - } - } - } - - set_rx_tx_status0(SaveRState, SaveTState); - return 1; -} - -static inline void dispatch_endpt(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - /* If ISTR_CTR is set and the ISTR gave us this EP_ID to handle, - * then presumably at least one of CTR_RX and CTR_TX is set, but - * again, ST's control flow allows for the possibility of neither. - * - * TODO try to find out if neither being set is possible. */ - if (epr & USB_EP_CTR_RX) { - usb_clear_ctr_rx(ep); - (USBLIB->ep_int_out[ep - 1])(); - } - if (epr & USB_EP_CTR_TX) { - usb_clear_ctr_tx(ep); - (USBLIB->ep_int_in[ep - 1])(); - } -} - -static inline void set_rx_tx_status0(uint16 rx, uint16 tx) { - usb_set_ep_rx_stat(USB_EP0, rx); - usb_set_ep_tx_stat(USB_EP0, tx); -} - -/* TODO Rip out usb_lib/ dependency from the following functions: */ - -static void handle_setup0(void) { - Setup0_Process(); -} - -static void handle_in0(void) { - In0_Process(); -} - -static void handle_out0(void) { - Out0_Process(); -} diff --git a/STM32F3/cores/maple/libmaple/usb/usb_cdcacm.c b/STM32F3/cores/maple/libmaple/usb/usb_cdcacm.c deleted file mode 100644 index bafb90b..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_cdcacm.c +++ /dev/null @@ -1,723 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/usb/stm32f1/usb_cdcacm.c - * @brief USB CDC ACM (a.k.a. virtual serial terminal, VCOM). - * - * FIXME: this works on the STM32F1 USB peripherals, and probably no - * place else. Nonportable bits really need to be factored out, and - * the result made cleaner. - */ - -#include - -#include -#include -#include - -/* Private headers */ -#include "usb_lib_globals.h" -#include "usb_reg_map.h" - -/* usb_lib headers */ -#include "usb_type.h" -#include "usb_core.h" -#include "usb_def.h" - -/****************************************************************************** - ****************************************************************************** - *** - *** HACK ALERT! FIXME FIXME FIXME FIXME! - *** - *** A bunch of LeafLabs-specific configuration lives in here for - *** now. This mess REALLY needs to get teased apart, with - *** appropriate pieces moved into Wirish. - *** - ****************************************************************************** - *****************************************************************************/ - -#if !(defined(BOARD_maple_mini_f3)) -#warning USB CDC ACM relies on LeafLabs board-specific configuration.\ - You may have problems on non-LeafLabs boards. -#endif - -static void vcomDataTxCb(void); -static void vcomDataRxCb(void); -static uint8* vcomGetSetLineCoding(uint16); - -static void usbInit(void); -static void usbReset(void); -static RESULT usbDataSetup(uint8 request); -static RESULT usbNoDataSetup(uint8 request); -static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); -static uint8* usbGetDeviceDescriptor(uint16 length); -static uint8* usbGetConfigDescriptor(uint16 length); -static uint8* usbGetStringDescriptor(uint16 length); -static void usbSetConfiguration(void); -static void usbSetDeviceAddress(void); - -/* - * Descriptors - */ - -/* FIXME move to Wirish */ -#define LEAFLABS_ID_VENDOR 0x1EAF -#define MAPLE_ID_PRODUCT 0x0004 -static const usb_descriptor_device usbVcomDescriptor_Device = - USB_CDCACM_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT); - -typedef struct { - usb_descriptor_config_header Config_Header; - usb_descriptor_interface CCI_Interface; - CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader; - CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement; - CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM; - CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union; - usb_descriptor_endpoint ManagementEndpoint; - usb_descriptor_interface DCI_Interface; - usb_descriptor_endpoint DataOutEndpoint; - usb_descriptor_endpoint DataInEndpoint; -} __packed usb_descriptor_config; - -#define MAX_POWER (100 >> 1) -static const usb_descriptor_config usbVcomDescriptor_Config = { - .Config_Header = { - .bLength = sizeof(usb_descriptor_config_header), - .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, - .wTotalLength = sizeof(usb_descriptor_config), - .bNumInterfaces = 0x02, - .bConfigurationValue = 0x01, - .iConfiguration = 0x00, - .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | - USB_CONFIG_ATTR_SELF_POWERED), - .bMaxPower = MAX_POWER, - }, - - .CCI_Interface = { - .bLength = sizeof(usb_descriptor_interface), - .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, - .bInterfaceNumber = 0x00, - .bAlternateSetting = 0x00, - .bNumEndpoints = 0x01, - .bInterfaceClass = USB_INTERFACE_CLASS_CDC, - .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM, - .bInterfaceProtocol = 0x01, /* Common AT Commands */ - .iInterface = 0x00, - }, - - .CDC_Functional_IntHeader = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), - .bDescriptorType = 0x24, - .SubType = 0x00, - .Data = {0x01, 0x10}, - }, - - .CDC_Functional_CallManagement = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), - .bDescriptorType = 0x24, - .SubType = 0x01, - .Data = {0x03, 0x01}, - }, - - .CDC_Functional_ACM = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1), - .bDescriptorType = 0x24, - .SubType = 0x02, - .Data = {0x06}, - }, - - .CDC_Functional_Union = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), - .bDescriptorType = 0x24, - .SubType = 0x06, - .Data = {0x00, 0x01}, - }, - - .ManagementEndpoint = { - .bLength = sizeof(usb_descriptor_endpoint), - .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, - .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | - USB_CDCACM_MANAGEMENT_ENDP), - .bmAttributes = USB_EP_TYPE_INTERRUPT, - .wMaxPacketSize = USB_CDCACM_MANAGEMENT_EPSIZE, - .bInterval = 0xFF, - }, - - .DCI_Interface = { - .bLength = sizeof(usb_descriptor_interface), - .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, - .bInterfaceNumber = 0x01, - .bAlternateSetting = 0x00, - .bNumEndpoints = 0x02, - .bInterfaceClass = USB_INTERFACE_CLASS_DIC, - .bInterfaceSubClass = 0x00, /* None */ - .bInterfaceProtocol = 0x00, /* None */ - .iInterface = 0x00, - }, - - .DataOutEndpoint = { - .bLength = sizeof(usb_descriptor_endpoint), - .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, - .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | - USB_CDCACM_RX_ENDP), - .bmAttributes = USB_EP_TYPE_BULK, - .wMaxPacketSize = USB_CDCACM_RX_EPSIZE, - .bInterval = 0x00, - }, - - .DataInEndpoint = { - .bLength = sizeof(usb_descriptor_endpoint), - .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, - .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_CDCACM_TX_ENDP), - .bmAttributes = USB_EP_TYPE_BULK, - .wMaxPacketSize = USB_CDCACM_TX_EPSIZE, - .bInterval = 0x00, - }, -}; - -/* - String Descriptors: - - we may choose to specify any or none of the following string - identifiers: - - iManufacturer: LeafLabs - iProduct: Maple - iSerialNumber: NONE - iConfiguration: NONE - iInterface(CCI): NONE - iInterface(DCI): NONE - -*/ - -/* Unicode language identifier: 0x0409 is US English */ -/* FIXME move to Wirish */ -static const usb_descriptor_string usbVcomDescriptor_LangID = { - .bLength = USB_DESCRIPTOR_STRING_LEN(1), - .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, - .bString = {0x09, 0x04}, -}; - -/* FIXME move to Wirish */ -static const usb_descriptor_string usbVcomDescriptor_iManufacturer = { - .bLength = USB_DESCRIPTOR_STRING_LEN(8), - .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, - .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0, - 'L', 0, 'a', 0, 'b', 0, 's', 0}, -}; - -/* FIXME move to Wirish */ -static const usb_descriptor_string usbVcomDescriptor_iProduct = { - .bLength = USB_DESCRIPTOR_STRING_LEN(5), - .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, - .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0}, -}; - -static ONE_DESCRIPTOR Device_Descriptor = { - (uint8*)&usbVcomDescriptor_Device, - sizeof(usb_descriptor_device) -}; - -static ONE_DESCRIPTOR Config_Descriptor = { - (uint8*)&usbVcomDescriptor_Config, - sizeof(usb_descriptor_config) -}; - -#define N_STRING_DESCRIPTORS 3 -static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = { - {(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, - {(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)}, - {(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(5)} -}; - -/* - * Etc. - */ - -/* I/O state */ - -/* Received data */ -static volatile uint8 vcomBufferRx[USB_CDCACM_RX_EPSIZE]; -/* Read index into vcomBufferRx */ -static volatile uint32 rx_offset = 0; -/* Number of bytes left to transmit */ -static volatile uint32 n_unsent_bytes = 0; -/* Are we currently sending an IN packet? */ -static volatile uint8 transmitting = 0; -/* Number of unread bytes */ -static volatile uint32 n_unread_bytes = 0; - -/* Other state (line coding, DTR/RTS) */ - -static volatile usb_cdcacm_line_coding line_coding = { - /* This default is 115200 baud, 8N1. */ - .dwDTERate = 115200, - .bCharFormat = USB_CDCACM_STOP_BITS_1, - .bParityType = USB_CDCACM_PARITY_NONE, - .bDataBits = 8, -}; - -/* DTR in bit 0, RTS in bit 1. */ -static volatile uint8 line_dtr_rts = 0; - -/* - * Endpoint callbacks - */ - -static void (*ep_int_in[7])(void) = - {vcomDataTxCb, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process}; - -static void (*ep_int_out[7])(void) = - {NOP_Process, - NOP_Process, - vcomDataRxCb, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process}; - -/* - * Globals required by usb_lib/ - * - * Mark these weak so they can be overriden to implement other USB - * functionality. - */ - -#define NUM_ENDPTS 0x04 -__weak DEVICE Device_Table = { - .Total_Endpoint = NUM_ENDPTS, - .Total_Configuration = 1 -}; - -#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ -__weak DEVICE_PROP Device_Property = { - .Init = usbInit, - .Reset = usbReset, - .Process_Status_IN = NOP_Process, - .Process_Status_OUT = NOP_Process, - .Class_Data_Setup = usbDataSetup, - .Class_NoData_Setup = usbNoDataSetup, - .Class_Get_Interface_Setting = usbGetInterfaceSetting, - .GetDeviceDescriptor = usbGetDeviceDescriptor, - .GetConfigDescriptor = usbGetConfigDescriptor, - .GetStringDescriptor = usbGetStringDescriptor, - .RxEP_buffer = NULL, - .MaxPacketSize = MAX_PACKET_SIZE -}; - -__weak USER_STANDARD_REQUESTS User_Standard_Requests = { - .User_GetConfiguration = NOP_Process, - .User_SetConfiguration = usbSetConfiguration, - .User_GetInterface = NOP_Process, - .User_SetInterface = NOP_Process, - .User_GetStatus = NOP_Process, - .User_ClearFeature = NOP_Process, - .User_SetEndPointFeature = NOP_Process, - .User_SetDeviceFeature = NOP_Process, - .User_SetDeviceAddress = usbSetDeviceAddress -}; - -/* - * User hooks - */ - -static void (*rx_hook)(unsigned, void*) = 0; -static void (*iface_setup_hook)(unsigned, void*) = 0; - -void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)) { - if (hook_flags & USB_CDCACM_HOOK_RX) { - rx_hook = hook; - } - if (hook_flags & USB_CDCACM_HOOK_IFACE_SETUP) { - iface_setup_hook = hook; - } -} - -/* - * CDC ACM interface - */ - -void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) { - /* Present ourselves to the host. Writing 0 to "disc" pin must - * pull USB_DP pin up while leaving USB_DM pulled down by the - * transceiver. See USB 2.0 spec, section 7.1.7.3. */ - gpio_set_modef(disc_dev, disc_bit, GPIO_MODE_OUTPUT, GPIO_MODEF_TYPE_PP); - gpio_write_bit(disc_dev, disc_bit, 0); - - /* - * set USB_DP and USB_DM pins to alternate mode and set alternate function to USB - */ - gpio_set_modef(GPIOA, 12, GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(GPIOA, 11, GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_af(GPIOA, 12, GPIO_AF_14); - gpio_set_af(GPIOA, 11, GPIO_AF_14); - - /* Initialize the USB peripheral. */ - usb_init_usblib(USBLIB, ep_int_in, ep_int_out); -} - -void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) { - /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0 - * spec, section 7.1.7.3). */ - nvic_irq_disable(NVIC_USB_LP_CAN_RX0); - gpio_write_bit(disc_dev, disc_bit, 1); - - /* - * set USB_DP and USB_DM pins to input floating mode, reset alternate function to system default - */ - gpio_set_modef(GPIOA, 12, GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); - gpio_set_modef(GPIOA, 11, GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); - gpio_set_af(GPIOA, 12, GPIO_AF_0); - gpio_set_af(GPIOA, 11, GPIO_AF_0); -} - -void usb_cdcacm_putc(char ch) { - while (!usb_cdcacm_tx((uint8*)&ch, 1)) - ; -} - -/* This function is non-blocking. - * - * It copies data from a usercode buffer into the USB peripheral TX - * buffer, and returns the number of bytes copied. */ -uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { - /* Last transmission hasn't finished, so abort. */ - if (usb_cdcacm_is_transmitting()) { - return 0; - } - - /* We can only put USB_CDCACM_TX_EPSIZE bytes in the buffer. */ - if (len > USB_CDCACM_TX_EPSIZE) { - len = USB_CDCACM_TX_EPSIZE; - } - - /* Queue bytes for sending. */ - if (len) { - usb_copy_to_pma(buf, len, USB_CDCACM_TX_ADDR); - } - // We still need to wait for the interrupt, even if we're sending - // zero bytes. (Sending zero-size packets is useful for flushing - // host-side buffers.) - usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, len); - n_unsent_bytes = len; - transmitting = 1; - usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID); - - return len; -} - -uint32 usb_cdcacm_data_available(void) { - return n_unread_bytes; -} - -uint8 usb_cdcacm_is_transmitting(void) { - return transmitting; -} - -uint16 usb_cdcacm_get_pending(void) { - return n_unsent_bytes; -} - -/* Nonblocking byte receive. - * - * Copies up to len bytes from our private data buffer (*NOT* the PMA) - * into buf and deq's the FIFO. */ -uint32 usb_cdcacm_rx(uint8* buf, uint32 len) { - /* Copy bytes to buffer. */ - uint32 n_copied = usb_cdcacm_peek(buf, len); - - /* Mark bytes as read. */ - n_unread_bytes -= n_copied; - rx_offset += n_copied; - - /* If all bytes have been read, re-enable the RX endpoint, which - * was set to NAK when the current batch of bytes was received. */ - if (n_unread_bytes == 0) { - usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); - rx_offset = 0; - } - - return n_copied; -} - -/* Nonblocking byte lookahead. - * - * Looks at unread bytes without marking them as read. */ -uint32 usb_cdcacm_peek(uint8* buf, uint32 len) { - int i; - - if (len > n_unread_bytes) { - len = n_unread_bytes; - } - - for (i = 0; i < len; i++) { - buf[i] = vcomBufferRx[i + rx_offset]; - } - - return len; -} - -uint8 usb_cdcacm_get_dtr() { - return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_DTR) != 0); -} - -uint8 usb_cdcacm_get_rts() { - return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_RTS) != 0); -} - -void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding *ret) { - ret->dwDTERate = line_coding.dwDTERate; - ret->bCharFormat = line_coding.bCharFormat; - ret->bParityType = line_coding.bParityType; - ret->bDataBits = line_coding.bDataBits; -} - -int usb_cdcacm_get_baud(void) { - return line_coding.dwDTERate; -} - -int usb_cdcacm_get_stop_bits(void) { - return line_coding.bCharFormat; -} - -int usb_cdcacm_get_parity(void) { - return line_coding.bParityType; -} - -int usb_cdcacm_get_n_data_bits(void) { - return line_coding.bDataBits; -} - - -/* - * Callbacks - */ - -static void vcomDataTxCb(void) { - n_unsent_bytes = 0; - transmitting = 0; -} - -static void vcomDataRxCb(void) { - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_NAK); - n_unread_bytes = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP); - /* This copy won't overwrite unread bytes, since we've set the RX - * endpoint to NAK, and will only set it to VALID when all bytes - * have been read. */ - usb_copy_from_pma((uint8*)vcomBufferRx, n_unread_bytes, - USB_CDCACM_RX_ADDR); - - - if (n_unread_bytes == 0) { - usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); - rx_offset = 0; - } - - if (rx_hook) { - rx_hook(USB_CDCACM_HOOK_RX, 0); - } -} - -static uint8* vcomGetSetLineCoding(uint16 length) { - if (length == 0) { - pInformation->Ctrl_Info.Usb_wLength = sizeof(struct usb_cdcacm_line_coding); - } - return (uint8*)&line_coding; -} - -static void usbInit(void) { - pInformation->Current_Configuration = 0; - - USB_BASE->CNTR = USB_CNTR_FRES; - - USBLIB->irq_mask = 0; - USB_BASE->CNTR = USBLIB->irq_mask; - USB_BASE->ISTR = 0; - USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - USB_BASE->CNTR = USBLIB->irq_mask; - - USB_BASE->ISTR = 0; - USBLIB->irq_mask = USB_ISR_MSK; - USB_BASE->CNTR = USBLIB->irq_mask; - - nvic_irq_enable(NVIC_USB_LP_CAN_RX0); - USBLIB->state = USB_UNCONNECTED; -} - -#define BTABLE_ADDRESS 0x00 -static void usbReset(void) { - pInformation->Current_Configuration = 0; - - /* current feature is current bmAttributes */ - pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED | - USB_CONFIG_ATTR_SELF_POWERED); - - USB_BASE->BTABLE = BTABLE_ADDRESS; - - /* setup control endpoint 0 */ - usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL); - usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL); - usb_set_ep_rx_addr(USB_EP0, USB_CDCACM_CTRL_RX_ADDR); - usb_set_ep_tx_addr(USB_EP0, USB_CDCACM_CTRL_TX_ADDR); - usb_clear_status_out(USB_EP0); - - usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize); - usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); - - /* setup management endpoint 1 */ - usb_set_ep_type(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_EP_TYPE_INTERRUPT); - usb_set_ep_tx_addr(USB_CDCACM_MANAGEMENT_ENDP, - USB_CDCACM_MANAGEMENT_ADDR); - usb_set_ep_tx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_TX_NAK); - usb_set_ep_rx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_RX_DISABLED); - - /* TODO figure out differences in style between RX/TX EP setup */ - - /* set up data endpoint OUT (RX) */ - usb_set_ep_type(USB_CDCACM_RX_ENDP, USB_EP_EP_TYPE_BULK); - usb_set_ep_rx_addr(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_ADDR); - usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); - - /* set up data endpoint IN (TX) */ - usb_set_ep_type(USB_CDCACM_TX_ENDP, USB_EP_EP_TYPE_BULK); - usb_set_ep_tx_addr(USB_CDCACM_TX_ENDP, USB_CDCACM_TX_ADDR); - usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_NAK); - usb_set_ep_rx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_RX_DISABLED); - - USBLIB->state = USB_ATTACHED; - SetDeviceAddress(0); - - /* Reset the RX/TX state */ - n_unread_bytes = 0; - n_unsent_bytes = 0; - rx_offset = 0; -} - -static RESULT usbDataSetup(uint8 request) { - uint8* (*CopyRoutine)(uint16) = 0; - - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { - switch (request) { - case USB_CDCACM_GET_LINE_CODING: - CopyRoutine = vcomGetSetLineCoding; - break; - case USB_CDCACM_SET_LINE_CODING: - CopyRoutine = vcomGetSetLineCoding; - break; - default: - break; - } - - /* Call the user hook. */ - if (iface_setup_hook) { - uint8 req_copy = request; - iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy); - } - } - - if (CopyRoutine == NULL) { - return USB_UNSUPPORT; - } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; -} - -static RESULT usbNoDataSetup(uint8 request) { - RESULT ret = USB_UNSUPPORT; - - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { - switch (request) { - case USB_CDCACM_SET_COMM_FEATURE: - /* We support set comm. feature, but don't handle it. */ - ret = USB_SUCCESS; - break; - case USB_CDCACM_SET_CONTROL_LINE_STATE: - /* Track changes to DTR and RTS. */ - line_dtr_rts = (pInformation->USBwValues.bw.bb0 & - (USB_CDCACM_CONTROL_LINE_DTR | - USB_CDCACM_CONTROL_LINE_RTS)); - ret = USB_SUCCESS; - break; - } - - /* Call the user hook. */ - if (iface_setup_hook) { - uint8 req_copy = request; - iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy); - } - } - return ret; -} - -static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) { - if (alt_setting > 0) { - return USB_UNSUPPORT; - } else if (interface > 1) { - return USB_UNSUPPORT; - } - - return USB_SUCCESS; -} - -static uint8* usbGetDeviceDescriptor(uint16 length) { - return Standard_GetDescriptorData(length, &Device_Descriptor); -} - -static uint8* usbGetConfigDescriptor(uint16 length) { - return Standard_GetDescriptorData(length, &Config_Descriptor); -} - -static uint8* usbGetStringDescriptor(uint16 length) { - uint8 wValue0 = pInformation->USBwValue0; - - if (wValue0 > N_STRING_DESCRIPTORS) { - return NULL; - } - return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); -} - -static void usbSetConfiguration(void) { - if (pInformation->Current_Configuration != 0) { - USBLIB->state = USB_CONFIGURED; - } -} - -static void usbSetDeviceAddress(void) { - USBLIB->state = USB_ADDRESSED; -} diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_core.c b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_core.c deleted file mode 100644 index 5cf9e87..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_core.c +++ /dev/null @@ -1,1013 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_core.c -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Standard protocol processing (USB v2.0) -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -#define ValBit(VAR,Place) (VAR & (1 << Place)) -#define SetBit(VAR,Place) (VAR |= (1 << Place)) -#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255)) - -#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \ - vSetEPTxStatus(EP_TX_VALID); \ - } - -#define vSetEPRxStatus(st) (SaveRState = st) -#define vSetEPTxStatus(st) (SaveTState = st) - -#define USB_StatusIn() Send0LengthData() -#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID) - -#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 & bb1 */ -#define StatusInfo1 StatusInfo.bw.bb0 - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -u16_u8 StatusInfo; -USB_Bool Data_Mul_MaxPacketSize = FALSE; -/* Private function prototypes -----------------------------------------------*/ -static void DataStageOut(void); -static void DataStageIn(void); -static void NoData_Setup0(void); -static void Data_Setup0(void); -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : Standard_GetConfiguration. -* Description : Return the current configuration variable address. -* Input : Length - How many bytes are needed. -* Output : None. -* Return : Return 1 , if the request is invalid when "Length" is 0. -* Return "Buffer" if the "Length" is not 0. -*******************************************************************************/ -u8 *Standard_GetConfiguration(u16 Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = - sizeof(pInformation->Current_Configuration); - return 0; - } - pUser_Standard_Requests->User_GetConfiguration(); - return (u8 *)&pInformation->Current_Configuration; -} - -/******************************************************************************* -* Function Name : Standard_SetConfiguration. -* Description : This routine is called to set the configuration value -* Then each class should configure device themself. -* Input : None. -* Output : None. -* Return : Return USB_SUCCESS, if the request is performed. -* Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetConfiguration(void) -{ - - if ((pInformation->USBwValue0 <= - Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0) - && (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/ - { - pInformation->Current_Configuration = pInformation->USBwValue0; - pUser_Standard_Requests->User_SetConfiguration(); - return USB_SUCCESS; - } - else - { - return USB_UNSUPPORT; - } -} - -/******************************************************************************* -* Function Name : Standard_GetInterface. -* Description : Return the Alternate Setting of the current interface. -* Input : Length - How many bytes are needed. -* Output : None. -* Return : Return 0, if the request is invalid when "Length" is 0. -* Return "Buffer" if the "Length" is not 0. -*******************************************************************************/ -u8 *Standard_GetInterface(u16 Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = - sizeof(pInformation->Current_AlternateSetting); - return 0; - } - pUser_Standard_Requests->User_GetInterface(); - return (u8 *)&pInformation->Current_AlternateSetting; -} - -/******************************************************************************* -* Function Name : Standard_SetInterface. -* Description : This routine is called to set the interface. -* Then each class should configure the interface them self. -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetInterface(void) -{ - RESULT Re; - /*Test if the specified Interface and Alternate Setting are supported by - the application Firmware*/ - Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0); - - if (pInformation->Current_Configuration != 0) - { - if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0) - || (pInformation->USBwValue1 != 0)) - { - return USB_UNSUPPORT; - } - else if (Re == USB_SUCCESS) - { - pUser_Standard_Requests->User_SetInterface(); - pInformation->Current_Interface = pInformation->USBwIndex0; - pInformation->Current_AlternateSetting = pInformation->USBwValue0; - return USB_SUCCESS; - } - - } - - return USB_UNSUPPORT; -} - -/******************************************************************************* -* Function Name : Standard_GetStatus. -* Description : Copy the device request data to "StatusInfo buffer". -* Input : - Length - How many bytes are needed. -* Output : None. -* Return : Return 0, if the request is at end of data block, -* or is invalid when "Length" is 0. -*******************************************************************************/ -u8 *Standard_GetStatus(u16 Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = 2; - return 0; - } - - StatusInfo.w = 0; - /* Reset Status Information */ - - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - /*Get Device Status */ - u8 Feature = pInformation->Current_Feature; - - /* Remote Wakeup enabled */ - if (ValBit(Feature, 5)) - { - SetBit(StatusInfo0, 1); - } - - /* Bus-powered */ - if (ValBit(Feature, 6)) - { - ClrBit(StatusInfo0, 0); - } - else /* Self-powered */ - { - SetBit(StatusInfo0, 0); - } - } - /*Interface Status*/ - else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - { - return (u8 *)&StatusInfo; - } - /*Get EndPoint Status*/ - else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - { - u8 Related_Endpoint; - u8 wIndex0 = pInformation->USBwIndex0; - - Related_Endpoint = (wIndex0 & 0x0f); - if (ValBit(wIndex0, 7)) - { - /* IN endpoint */ - if (_GetTxStallStatus(Related_Endpoint)) - { - SetBit(StatusInfo0, 0); /* IN Endpoint stalled */ - } - } - else - { - /* OUT endpoint */ - if (_GetRxStallStatus(Related_Endpoint)) - { - SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */ - } - } - - } - else - { - return NULL; - } - pUser_Standard_Requests->User_GetStatus(); - return (u8 *)&StatusInfo; -} - -/******************************************************************************* -* Function Name : Standard_ClearFeature. -* Description : Clear or disable a specific feature. -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_ClearFeature(void) -{ - u32 Type_Rec = Type_Recipient; - u32 Status; - - - if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - {/*Device Clear Feature*/ - ClrBit(pInformation->Current_Feature, 5); - return USB_SUCCESS; - } - else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - {/*EndPoint Clear Feature*/ - DEVICE* pDev; - u32 Related_Endpoint; - u32 wIndex0; - u32 rEP; - - if ((pInformation->USBwValue != ENDPOINT_STALL) - || (pInformation->USBwIndex1 != 0)) - { - return USB_UNSUPPORT; - } - - pDev = &Device_Table; - wIndex0 = pInformation->USBwIndex0; - rEP = wIndex0 & ~0x80; - Related_Endpoint = ENDP0 + rEP; - - if (ValBit(pInformation->USBwIndex0, 7)) - { - /*Get Status of endpoint & stall the request if the related_ENdpoint - is Disabled*/ - Status = _GetEPTxStatus(Related_Endpoint); - } - else - { - Status = _GetEPRxStatus(Related_Endpoint); - } - - if ((rEP >= pDev->Total_Endpoint) || (Status == 0) - || (pInformation->Current_Configuration == 0)) - { - return USB_UNSUPPORT; - } - - - if (wIndex0 & 0x80) - { - /* IN endpoint */ - if (_GetTxStallStatus(Related_Endpoint )) - { - ClearDTOG_TX(Related_Endpoint); - SetEPTxStatus(Related_Endpoint, EP_TX_VALID); - } - } - else - { - /* OUT endpoint */ - if (_GetRxStallStatus(Related_Endpoint)) - { - if (Related_Endpoint == ENDP0) - { - /* After clear the STALL, enable the default endpoint receiver */ - SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize); - _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); - } - else - { - ClearDTOG_RX(Related_Endpoint); - _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); - } - } - } - pUser_Standard_Requests->User_ClearFeature(); - return USB_SUCCESS; - } - - return USB_UNSUPPORT; -} - -/******************************************************************************* -* Function Name : Standard_SetEndPointFeature -* Description : Set or enable a specific feature of EndPoint -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetEndPointFeature(void) -{ - u32 wIndex0; - u32 Related_Endpoint; - u32 rEP; - u32 Status; - - wIndex0 = pInformation->USBwIndex0; - rEP = wIndex0 & ~0x80; - Related_Endpoint = ENDP0 + rEP; - - if (ValBit(pInformation->USBwIndex0, 7)) - { - /* get Status of endpoint & stall the request if the related_ENdpoint - is Disabled*/ - Status = _GetEPTxStatus(Related_Endpoint); - } - else - { - Status = _GetEPRxStatus(Related_Endpoint); - } - - if (Related_Endpoint >= Device_Table.Total_Endpoint - || pInformation->USBwValue != 0 || Status == 0 - || pInformation->Current_Configuration == 0) - { - return USB_UNSUPPORT; - } - else - { - if (wIndex0 & 0x80) - { - /* IN endpoint */ - _SetEPTxStatus(Related_Endpoint, EP_TX_STALL); - } - - else - { - /* OUT endpoint */ - _SetEPRxStatus(Related_Endpoint, EP_RX_STALL); - } - } - pUser_Standard_Requests->User_SetEndPointFeature(); - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Standard_SetDeviceFeature. -* Description : Set or enable a specific feature of Device. -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetDeviceFeature(void) -{ - SetBit(pInformation->Current_Feature, 5); - pUser_Standard_Requests->User_SetDeviceFeature(); - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Standard_GetDescriptorData. -* Description : Standard_GetDescriptorData is used for descriptors transfer. -* : This routine is used for the descriptors resident in Flash -* or RAM -* pDesc can be in either Flash or RAM -* The purpose of this routine is to have a versatile way to -* response descriptors request. It allows user to generate -* certain descriptors with software or read descriptors from -* external storage part by part. -* Input : - Length - Length of the data in this transfer. -* - pDesc - A pointer points to descriptor struct. -* The structure gives the initial address of the descriptor and -* its original size. -* Output : None. -* Return : Address of a part of the descriptor pointed by the Usb_ -* wOffset The buffer pointed by this address contains at least -* Length bytes. -*******************************************************************************/ -u8 *Standard_GetDescriptorData(u16 Length, ONE_DESCRIPTOR *pDesc) -{ - u32 wOffset; - - wOffset = pInformation->Ctrl_Info.Usb_wOffset; - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset; - return 0; - } - - return pDesc->Descriptor + wOffset; -} - -/******************************************************************************* -* Function Name : DataStageOut. -* Description : Data stage of a Control Write Transfer. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void DataStageOut(void) -{ - ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; - u32 save_rLength; - - save_rLength = pEPinfo->Usb_rLength; - - if (pEPinfo->CopyData && save_rLength) - { - u8 *Buffer; - u32 Length; - - Length = pEPinfo->PacketSize; - if (Length > save_rLength) - { - Length = save_rLength; - } - - Buffer = (*pEPinfo->CopyData)(Length); - pEPinfo->Usb_rLength -= Length; - pEPinfo->Usb_rOffset += Length; - - PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); - } - - if (pEPinfo->Usb_rLength != 0) - { - vSetEPRxStatus(EP_RX_VALID);/* re-enable for next data reception */ - SetEPTxCount(ENDP0, 0); - vSetEPTxStatus(EP_TX_VALID);/* Expect the host to abort the data OUT stage */ - } - /* Set the next State*/ - if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) - { - pInformation->ControlState = OUT_DATA; - } - else - { - if (pEPinfo->Usb_rLength > 0) - { - pInformation->ControlState = LAST_OUT_DATA; - } - else if (pEPinfo->Usb_rLength == 0) - { - pInformation->ControlState = WAIT_STATUS_IN; - USB_StatusIn(); - } - } -} - -/******************************************************************************* -* Function Name : DataStageIn. -* Description : Data stage of a Control Read Transfer. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void DataStageIn(void) -{ - ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; - u32 save_wLength = pEPinfo->Usb_wLength; - u32 ControlState = pInformation->ControlState; - - u8 *DataBuffer; - u32 Length; - - if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) - { - if(Data_Mul_MaxPacketSize == TRUE) - { - /* No more data to send and empty packet */ - Send0LengthData(); - ControlState = LAST_IN_DATA; - Data_Mul_MaxPacketSize = FALSE; - } - else - { - /* No more data to send so STALL the TX Status*/ - ControlState = WAIT_STATUS_OUT; - vSetEPTxStatus(EP_TX_STALL); - } - - goto Expect_Status_Out; - } - - Length = pEPinfo->PacketSize; - ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA; - - if (Length > save_wLength) - { - Length = save_wLength; - } - - DataBuffer = (*pEPinfo->CopyData)(Length); - - UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); - - SetEPTxCount(ENDP0, Length); - - pEPinfo->Usb_wLength -= Length; - pEPinfo->Usb_wOffset += Length; - vSetEPTxStatus(EP_TX_VALID); - - USB_StatusOut();/* Expect the host to abort the data IN stage */ - -Expect_Status_Out: - pInformation->ControlState = ControlState; -} - -/******************************************************************************* -* Function Name : NoData_Setup0. -* Description : Proceed the processing of setup request without data stage. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void NoData_Setup0(void) -{ - RESULT Result = USB_UNSUPPORT; - u32 RequestNo = pInformation->USBbRequest; - u32 ControlState; - - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - /* Device Request*/ - /* SET_CONFIGURATION*/ - if (RequestNo == SET_CONFIGURATION) - { - Result = Standard_SetConfiguration(); - } - - /*SET ADDRESS*/ - else if (RequestNo == SET_ADDRESS) - { - if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0) - || (pInformation->USBwIndex != 0) - || (pInformation->Current_Configuration != 0)) - /* Device Address should be 127 or less*/ - { - ControlState = STALLED; - goto exit_NoData_Setup0; - } - else - { - Result = USB_SUCCESS; - } - } - /*SET FEATURE for Device*/ - else if (RequestNo == SET_FEATURE) - { - if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) - && (pInformation->USBwIndex == 0) - && (ValBit(pInformation->Current_Feature, 5))) - { - Result = Standard_SetDeviceFeature(); - } - else - { - Result = USB_UNSUPPORT; - } - } - /*Clear FEATURE for Device */ - else if (RequestNo == CLEAR_FEATURE) - { - if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP - && pInformation->USBwIndex == 0 - && ValBit(pInformation->Current_Feature, 5)) - { - Result = Standard_ClearFeature(); - } - else - { - Result = USB_UNSUPPORT; - } - } - - } - - /* Interface Request*/ - else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - { - /*SET INTERFACE*/ - if (RequestNo == SET_INTERFACE) - { - Result = Standard_SetInterface(); - } - } - - /* EndPoint Request*/ - else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - { - /*CLEAR FEATURE for EndPoint*/ - if (RequestNo == CLEAR_FEATURE) - { - Result = Standard_ClearFeature(); - } - /* SET FEATURE for EndPoint*/ - else if (RequestNo == SET_FEATURE) - { - Result = Standard_SetEndPointFeature(); - } - } - else - { - Result = USB_UNSUPPORT; - } - - - if (Result != USB_SUCCESS) - { - Result = (*pProperty->Class_NoData_Setup)(RequestNo); - if (Result == USB_NOT_READY) - { - ControlState = PAUSE; - goto exit_NoData_Setup0; - } - } - - if (Result != USB_SUCCESS) - { - ControlState = STALLED; - goto exit_NoData_Setup0; - } - - ControlState = WAIT_STATUS_IN;/* After no data stage SETUP */ - - USB_StatusIn(); - -exit_NoData_Setup0: - pInformation->ControlState = ControlState; - return; -} - -/******************************************************************************* -* Function Name : Data_Setup0. -* Description : Proceed the processing of setup request with data stage. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Data_Setup0(void) -{ - u8 *(*CopyRoutine)(u16); - RESULT Result; - u32 Request_No = pInformation->USBbRequest; - - u32 Related_Endpoint, Reserved; - u32 wOffset, Status; - - - - CopyRoutine = NULL; - wOffset = 0; - - if (Request_No == GET_DESCRIPTOR) - { - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - u8 wValue1 = pInformation->USBwValue1; - if (wValue1 == DEVICE_DESCRIPTOR) - { - CopyRoutine = pProperty->GetDeviceDescriptor; - } - else if (wValue1 == CONFIG_DESCRIPTOR) - { - CopyRoutine = pProperty->GetConfigDescriptor; - } - else if (wValue1 == STRING_DESCRIPTOR) - { - CopyRoutine = pProperty->GetStringDescriptor; - } /* End of GET_DESCRIPTOR */ - } - } - - /*GET STATUS*/ - else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0) - && (pInformation->USBwLength == 0x0002) - && (pInformation->USBwIndex1 == 0)) - { - /* GET STATUS for Device*/ - if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - && (pInformation->USBwIndex == 0)) - { - CopyRoutine = Standard_GetStatus; - } - - /* GET STATUS for Interface*/ - else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - { - if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS) - && (pInformation->Current_Configuration != 0)) - { - CopyRoutine = Standard_GetStatus; - } - } - - /* GET STATUS for EndPoint*/ - else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - { - Related_Endpoint = (pInformation->USBwIndex0 & 0x0f); - Reserved = pInformation->USBwIndex0 & 0x70; - - if (ValBit(pInformation->USBwIndex0, 7)) - { - /*Get Status of endpoint & stall the request if the related_ENdpoint - is Disabled*/ - Status = _GetEPTxStatus(Related_Endpoint); - } - else - { - Status = _GetEPRxStatus(Related_Endpoint); - } - - if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0) - && (Status != 0)) - { - CopyRoutine = Standard_GetStatus; - } - } - - } - - /*GET CONFIGURATION*/ - else if (Request_No == GET_CONFIGURATION) - { - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - CopyRoutine = Standard_GetConfiguration; - } - } - /*GET INTERFACE*/ - else if (Request_No == GET_INTERFACE) - { - if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - && (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0) - && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001) - && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)) - { - CopyRoutine = Standard_GetInterface; - } - - } - - if (CopyRoutine) - { - pInformation->Ctrl_Info.Usb_wOffset = wOffset; - pInformation->Ctrl_Info.CopyData = CopyRoutine; - /* sb in the original the cast to word was directly */ - /* now the cast is made step by step */ - (*CopyRoutine)(0); - Result = USB_SUCCESS; - } - else - { - Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest); - if (Result == USB_NOT_READY) - { - pInformation->ControlState = PAUSE; - return; - } - } - - if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) - { - /* Data is not ready, wait it */ - pInformation->ControlState = PAUSE; - return; - } - if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0)) - { - /* Unsupported request */ - pInformation->ControlState = STALLED; - return; - } - - - if (ValBit(pInformation->USBbmRequestType, 7)) - { - /* Device ==> Host */ - vu32 wLength = pInformation->USBwLength; - - /* Restrict the data length to be the one host asks */ - if (pInformation->Ctrl_Info.Usb_wLength > wLength) - { - pInformation->Ctrl_Info.Usb_wLength = wLength; - } - - else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) - { - if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) - { - Data_Mul_MaxPacketSize = FALSE; - } - else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) - { - Data_Mul_MaxPacketSize = TRUE; - } - } - - pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize; - DataStageIn(); - } - else - { - pInformation->ControlState = OUT_DATA; - vSetEPRxStatus(EP_RX_VALID); /* enable for next data reception */ - } - - return; -} - -/******************************************************************************* -* Function Name : Setup0_Process -* Description : Get the device request data and dispatch to individual process. -* Input : None. -* Output : None. -* Return : Post0_Process. -*******************************************************************************/ -u8 Setup0_Process(void) -{ - - union - { - u8* b; - u16* w; - } pBuf; - - pBuf.b = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ - - if (pInformation->ControlState != PAUSE) - { - pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */ - pInformation->USBbRequest = *pBuf.b++; /* bRequest */ - pBuf.w++; /* word not accessed because of 32 bits addressing */ - pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */ - pBuf.w++; /* word not accessed because of 32 bits addressing */ - pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */ - pBuf.w++; /* word not accessed because of 32 bits addressing */ - pInformation->USBwLength = *pBuf.w; /* wLength */ - } - - pInformation->ControlState = SETTING_UP; - if (pInformation->USBwLength == 0) - { - /* Setup with no data stage */ - NoData_Setup0(); - } - else - { - /* Setup with data stage */ - Data_Setup0(); - } - return Post0_Process(); -} - -/******************************************************************************* -* Function Name : In0_Process -* Description : Process the IN token on all default endpoint. -* Input : None. -* Output : None. -* Return : Post0_Process. -*******************************************************************************/ -u8 In0_Process(void) -{ - u32 ControlState = pInformation->ControlState; - - if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) - { - DataStageIn(); - /* ControlState may be changed outside the function */ - ControlState = pInformation->ControlState; - } - - else if (ControlState == WAIT_STATUS_IN) - { - if ((pInformation->USBbRequest == SET_ADDRESS) && - (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) - { - SetDeviceAddress(pInformation->USBwValue0); - pUser_Standard_Requests->User_SetDeviceAddress(); - } - (*pProperty->Process_Status_IN)(); - ControlState = STALLED; - } - - else - { - ControlState = STALLED; - } - - pInformation->ControlState = ControlState; - - return Post0_Process(); -} - -/******************************************************************************* -* Function Name : Out0_Process -* Description : Process the OUT token on all default endpoint. -* Input : None. -* Output : None. -* Return : Post0_Process. -*******************************************************************************/ -u8 Out0_Process(void) -{ - u32 ControlState = pInformation->ControlState; - - if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA)) - { - DataStageOut(); - ControlState = pInformation->ControlState; /* may be changed outside the function */ - } - - else if (ControlState == WAIT_STATUS_OUT) - { - (*pProperty->Process_Status_OUT)(); - ControlState = STALLED; - } - - else if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) - { - /* host aborts the transfer before finish */ - ControlState = STALLED; - } - - /* Unexpect state, STALL the endpoint */ - else - { - ControlState = STALLED; - } - - pInformation->ControlState = ControlState; - - return Post0_Process(); -} - -/******************************************************************************* -* Function Name : Post0_Process -* Description : Stall the Endpoint 0 in case of error. -* Input : None. -* Output : None. -* Return : - 0 if the control State is in PAUSE -* - 1 if not. -*******************************************************************************/ -u8 Post0_Process(void) -{ - SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); - - if (pInformation->ControlState == STALLED) - { - vSetEPRxStatus(EP_RX_STALL); - vSetEPTxStatus(EP_TX_STALL); - } - - return (pInformation->ControlState == PAUSE); -} - -/******************************************************************************* -* Function Name : SetDeviceAddress. -* Description : Set the device and all the used Endpoints addresses. -* Input : - Val: device adress. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetDeviceAddress(u8 Val) -{ - u32 i; - u32 nEP = Device_Table.Total_Endpoint; - - /* set address in every used endpoint */ - for (i = 0; i < nEP; i++) - { - _SetEPAddress((u8)i, (u8)i); - } /* for */ - _SetDADDR(Val | DADDR_EF); /* set device address and enable function */ -} - -/******************************************************************************* -* Function Name : NOP_Process -* Description : No operation function. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void NOP_Process(void) -{ -} - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_core.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_core.h deleted file mode 100644 index fa29a18..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_core.h +++ /dev/null @@ -1,251 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_core.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Standard protocol processing functions prototypes -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_CORE_H -#define __USB_CORE_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef enum _CONTROL_STATE -{ - WAIT_SETUP, /* 0 */ - SETTING_UP, /* 1 */ - IN_DATA, /* 2 */ - OUT_DATA, /* 3 */ - LAST_IN_DATA, /* 4 */ - LAST_OUT_DATA, /* 5 */ - WAIT_STATUS_IN, /* 7 */ - WAIT_STATUS_OUT, /* 8 */ - STALLED, /* 9 */ - PAUSE /* 10 */ -} CONTROL_STATE; /* The state machine states of a control pipe */ - -typedef struct OneDescriptor -{ - u8 *Descriptor; - u16 Descriptor_Size; -} -ONE_DESCRIPTOR, *PONE_DESCRIPTOR; -/* All the request process routines return a value of this type - If the return value is not SUCCESS or NOT_READY, - the software will STALL the correspond endpoint */ -typedef enum _RESULT -{ - USB_SUCCESS = 0, /* Process sucessfully */ - USB_ERROR, - USB_UNSUPPORT, - USB_NOT_READY /* The process has not been finished, endpoint will be - NAK to further rquest */ -} RESULT; - - -/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/ -typedef struct _ENDPOINT_INFO -{ - /* When send data out of the device, - CopyData() is used to get data buffer 'Length' bytes data - if Length is 0, - CopyData() returns the total length of the data - if the request is not supported, returns 0 - (NEW Feature ) - if CopyData() returns -1, the calling routine should not proceed - further and will resume the SETUP process by the class device - if Length is not 0, - CopyData() returns a pointer to indicate the data location - Usb_wLength is the data remain to be sent, - Usb_wOffset is the Offset of original data - When receive data from the host, - CopyData() is used to get user data buffer which is capable - of Length bytes data to copy data from the endpoint buffer. - if Length is 0, - CopyData() returns the available data length, - if Length is not 0, - CopyData() returns user buffer address - Usb_rLength is the data remain to be received, - Usb_rPointer is the Offset of data buffer - */ - u16 Usb_wLength; - u16 Usb_wOffset; - u16 PacketSize; - u8 *(*CopyData)(u16 Length); -}ENDPOINT_INFO; - -/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/ - -typedef struct _DEVICE -{ - u8 Total_Endpoint; /* Number of endpoints that are used */ - u8 Total_Configuration;/* Number of configuration available */ -} -DEVICE; - -typedef union -{ - u16 w; - struct BW - { - u8 bb1; - u8 bb0; - } - bw; -} u16_u8; - -typedef struct _DEVICE_INFO -{ - u8 USBbmRequestType; /* bmRequestType */ - u8 USBbRequest; /* bRequest */ - u16_u8 USBwValues; /* wValue */ - u16_u8 USBwIndexs; /* wIndex */ - u16_u8 USBwLengths; /* wLength */ - - u8 ControlState; /* of type CONTROL_STATE */ - u8 Current_Feature; - u8 Current_Configuration; /* Selected configuration */ - u8 Current_Interface; /* Selected interface of current configuration */ - u8 Current_AlternateSetting;/* Selected Alternate Setting of current - interface*/ - - ENDPOINT_INFO Ctrl_Info; -}DEVICE_INFO; - -typedef struct _DEVICE_PROP -{ - void (*Init)(void); /* Initialize the device */ - void (*Reset)(void); /* Reset routine of this device */ - - /* Device dependent process after the status stage */ - void (*Process_Status_IN)(void); - void (*Process_Status_OUT)(void); - - /* Procedure of process on setup stage of a class specified request with data stage */ - /* All class specified requests with data stage are processed in Class_Data_Setup - Class_Data_Setup() - responses to check all special requests and fills ENDPOINT_INFO - according to the request - If IN tokens are expected, then wLength & wOffset will be filled - with the total transferring bytes and the starting position - If OUT tokens are expected, then rLength & rOffset will be filled - with the total expected bytes and the starting position in the buffer - - If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT - - CAUTION: - Since GET_CONFIGURATION & GET_INTERFACE are highly related to - the individual classes, they will be checked and processed here. - */ - RESULT (*Class_Data_Setup)(u8 RequestNo); - - /* Procedure of process on setup stage of a class specified request without data stage */ - /* All class specified requests without data stage are processed in Class_NoData_Setup - Class_NoData_Setup - responses to check all special requests and perform the request - - CAUTION: - Since SET_CONFIGURATION & SET_INTERFACE are highly related to - the individual classes, they will be checked and processed here. - */ - RESULT (*Class_NoData_Setup)(u8 RequestNo); - - /*Class_Get_Interface_Setting - This function is used by the file usb_core.c to test if the selected Interface - and Alternate Setting (u8 Interface, u8 AlternateSetting) are supported by - the application. - This function is writing by user. It should return "SUCCESS" if the Interface - and Alternate Setting are supported by the application or "UNSUPPORT" if they - are not supported. */ - - RESULT (*Class_Get_Interface_Setting)(u8 Interface, u8 AlternateSetting); - - u8* (*GetDeviceDescriptor)(u16 Length); - u8* (*GetConfigDescriptor)(u16 Length); - u8* (*GetStringDescriptor)(u16 Length); - - u8* RxEP_buffer; - u8 MaxPacketSize; - -}DEVICE_PROP; - -typedef struct _USER_STANDARD_REQUESTS -{ - void (*User_GetConfiguration)(void); /* Get Configuration */ - void (*User_SetConfiguration)(void); /* Set Configuration */ - void (*User_GetInterface)(void); /* Get Interface */ - void (*User_SetInterface)(void); /* Set Interface */ - void (*User_GetStatus)(void); /* Get Status */ - void (*User_ClearFeature)(void); /* Clear Feature */ - void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */ - void (*User_SetDeviceFeature)(void); /* Set Device Feature */ - void (*User_SetDeviceAddress)(void); /* Set Device Address */ -} -USER_STANDARD_REQUESTS; - -/* Exported constants --------------------------------------------------------*/ -#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT)) - -#define Usb_rLength Usb_wLength -#define Usb_rOffset Usb_wOffset - -#define USBwValue USBwValues.w -#define USBwValue0 USBwValues.bw.bb0 -#define USBwValue1 USBwValues.bw.bb1 -#define USBwIndex USBwIndexs.w -#define USBwIndex0 USBwIndexs.bw.bb0 -#define USBwIndex1 USBwIndexs.bw.bb1 -#define USBwLength USBwLengths.w -#define USBwLength0 USBwLengths.bw.bb0 -#define USBwLength1 USBwLengths.bw.bb1 - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -u8 Setup0_Process(void); -u8 Post0_Process(void); -u8 Out0_Process(void); -u8 In0_Process(void); - -RESULT Standard_SetEndPointFeature(void); -RESULT Standard_SetDeviceFeature(void); - -u8 *Standard_GetConfiguration(u16 Length); -RESULT Standard_SetConfiguration(void); -u8 *Standard_GetInterface(u16 Length); -RESULT Standard_SetInterface(void); -u8 *Standard_GetDescriptorData(u16 Length, PONE_DESCRIPTOR pDesc); - -u8 *Standard_GetStatus(u16 Length); -RESULT Standard_ClearFeature(void); -void SetDeviceAddress(u8); -void NOP_Process(void); - -extern DEVICE_PROP Device_Property; -extern USER_STANDARD_REQUESTS User_Standard_Requests; -extern DEVICE Device_Table; -extern DEVICE_INFO Device_Info; - -/* cells saving status during interrupt servicing */ -extern u16 SaveRState; -extern u16 SaveTState; - -#if defined(__cplusplus) -} -#endif - -#endif /* __USB_CORE_H */ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_def.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_def.h deleted file mode 100644 index 80aa303..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_def.h +++ /dev/null @@ -1,88 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_def.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Definitions related to USB Core -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_DEF_H -#define __USB_DEF_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef enum _RECIPIENT_TYPE -{ - DEVICE_RECIPIENT, /* Recipient device */ - INTERFACE_RECIPIENT, /* Recipient interface */ - ENDPOINT_RECIPIENT, /* Recipient endpoint */ - OTHER_RECIPIENT -} RECIPIENT_TYPE; - - -typedef enum _STANDARD_REQUESTS -{ - GET_STATUS = 0, - CLEAR_FEATURE, - RESERVED1, - SET_FEATURE, - RESERVED2, - SET_ADDRESS, - GET_DESCRIPTOR, - SET_DESCRIPTOR, - GET_CONFIGURATION, - SET_CONFIGURATION, - GET_INTERFACE, - SET_INTERFACE, - TOTAL_sREQUEST, /* Total number of Standard request */ - SYNCH_FRAME = 12 -} STANDARD_REQUESTS; - -/* Definition of "USBwValue" */ -typedef enum _DESCRIPTOR_TYPE -{ - DEVICE_DESCRIPTOR = 1, - CONFIG_DESCRIPTOR, - STRING_DESCRIPTOR, - INTERFACE_DESCRIPTOR, - ENDPOINT_DESCRIPTOR -} DESCRIPTOR_TYPE; - -/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */ -typedef enum _FEATURE_SELECTOR -{ - ENDPOINT_STALL, - DEVICE_REMOTE_WAKEUP -} FEATURE_SELECTOR; - -/* Exported constants --------------------------------------------------------*/ -/* Definition of "USBbmRequestType" */ -#define REQUEST_TYPE 0x60 /* Mask to get request type */ -#define STANDARD_REQUEST 0x00 /* Standard request */ -#define CLASS_REQUEST 0x20 /* Class request */ -#define VENDOR_REQUEST 0x40 /* Vendor request */ - -#define RECIPIENT 0x1F /* Mask to get recipient */ - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -#if defined(__cplusplus) -} -#endif - -#endif /* __USB_DEF_H */ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_init.c b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_init.c deleted file mode 100644 index 94f3a83..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_init.c +++ /dev/null @@ -1,64 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_init.c -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Initialization routines & global variables -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* The number of current endpoint, it will be used to specify an endpoint */ - u8 EPindex; -/* The number of current device, it is an index to the Device_Table */ -/* u8 Device_no; */ -/* Points to the DEVICE_INFO structure of current device */ -/* The purpose of this register is to speed up the execution */ -DEVICE_INFO *pInformation; -/* Points to the DEVICE_PROP structure of current device */ -/* The purpose of this register is to speed up the execution */ -DEVICE_PROP *pProperty; -/* Temporary save the state of Rx & Tx status. */ -/* Whenever the Rx or Tx state is changed, its value is saved */ -/* in this variable first and will be set to the EPRB or EPRA */ -/* at the end of interrupt process */ -u16 SaveState ; -u16 wInterrupt_Mask; -DEVICE_INFO Device_Info; -USER_STANDARD_REQUESTS *pUser_Standard_Requests; - -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : USB_Init -* Description : USB system initialization -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void USB_Init(void) -{ - pInformation = &Device_Info; - pInformation->ControlState = 2; - pProperty = &Device_Property; - pUser_Standard_Requests = &User_Standard_Requests; - /* Initialize devices one by one */ - - pProperty->Init(); -} - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_init.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_init.h deleted file mode 100644 index 80ee2fb..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_init.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_init.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Initialization routines & global variables -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_INIT_H -#define __USB_INIT_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -void USB_Init(void); - -/* External variables --------------------------------------------------------*/ -/* The number of current endpoint, it will be used to specify an endpoint */ -extern u8 EPindex; -/* The number of current device, it is an index to the Device_Table */ -/*extern u8 Device_no; */ -/* Points to the DEVICE_INFO structure of current device */ -/* The purpose of this register is to speed up the execution */ -extern DEVICE_INFO* pInformation; -/* Points to the DEVICE_PROP structure of current device */ -/* The purpose of this register is to speed up the execution */ -extern DEVICE_PROP* pProperty; -/* Temporary save the state of Rx & Tx status. */ -/* Whenever the Rx or Tx state is changed, its value is saved */ -/* in this variable first and will be set to the EPRB or EPRA */ -/* at the end of interrupt process */ -extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; - -extern u16 SaveState ; -extern u16 wInterrupt_Mask; - -#if defined(__cplusplus) -} -#endif - -#endif /* __USB_INIT_H */ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_lib.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_lib.h deleted file mode 100644 index 85f94ab..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_lib.h +++ /dev/null @@ -1,36 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_lib.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : USB library include files -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_LIB_H -#define __USB_LIB_H - -/* Includes ------------------------------------------------------------------*/ -#include "usb_type.h" -#include "usb_regs.h" -#include "usb_def.h" -#include "usb_core.h" -#include "usb_init.h" -#include "usb_mem.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -/* External variables --------------------------------------------------------*/ - -#endif /* __USB_LIB_H */ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_mem.c b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_mem.c deleted file mode 100644 index ad9740a..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_mem.c +++ /dev/null @@ -1,73 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_mem.c -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Utility functions for memory transfers to/from PMA -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/******************************************************************************* -* Function Name : UserToPMABufferCopy -* Description : Copy a buffer from user memory area to packet memory area (PMA) -* Input : - pbUsrBuf: pointer to user memory area. -* - wPMABufAddr: address into PMA. -* - wNBytes: no. of bytes to be copied. -* Output : None. -* Return : None . -*******************************************************************************/ -void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) -{ - u32 n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */ - u32 i, temp1, temp2; - u16 *pdwVal; - pdwVal = (u16 *)(wPMABufAddr * 2 + PMAAddr); - for (i = n; i != 0; i--) - { - temp1 = (u16) * pbUsrBuf; - pbUsrBuf++; - temp2 = temp1 | (u16) * pbUsrBuf << 8; - *pdwVal++ = temp2; - pdwVal++; - pbUsrBuf++; - } -} -/******************************************************************************* -* Function Name : PMAToUserBufferCopy -* Description : Copy a buffer from user memory area to packet memory area (PMA) -* Input : - pbUsrBuf = pointer to user memory area. -* - wPMABufAddr = address into PMA. -* - wNBytes = no. of bytes to be copied. -* Output : None. -* Return : None. -*******************************************************************************/ -void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) -{ - u32 n = (wNBytes + 1) >> 1;/* /2*/ - u32 i; - u32 *pdwVal; - pdwVal = (u32 *)(wPMABufAddr * 2 + PMAAddr); - for (i = n; i != 0; i--) - { - *(u16*)pbUsrBuf++ = *pdwVal++; - pbUsrBuf++; - } -} - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_mem.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_mem.h deleted file mode 100644 index b0e0474..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_mem.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_mem.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Utility prototypes functions for memory/PMA transfers -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_MEM_H -#define __USB_MEM_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -#if defined(__cplusplus) -extern "C" { -#endif - -void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes); -void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes); - -#if defined(__cplusplus) -} -#endif - -/* External variables --------------------------------------------------------*/ - -#endif /*__USB_MEM_H*/ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_regs.c b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_regs.c deleted file mode 100644 index c7e0276..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_regs.c +++ /dev/null @@ -1,748 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_regs.c -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Interface functions to USB cell registers -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : SetCNTR. -* Description : Set the CNTR register value. -* Input : wRegValue: new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetCNTR(u16 wRegValue) -{ - _SetCNTR(wRegValue); -} - -/******************************************************************************* -* Function Name : GetCNTR. -* Description : returns the CNTR register value. -* Input : None. -* Output : None. -* Return : CNTR register Value. -*******************************************************************************/ -u16 GetCNTR(void) -{ - return(_GetCNTR()); -} - -/******************************************************************************* -* Function Name : SetISTR. -* Description : Set the ISTR register value. -* Input : wRegValue: new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetISTR(u16 wRegValue) -{ - _SetISTR(wRegValue); -} - -/******************************************************************************* -* Function Name : GetISTR -* Description : Returns the ISTR register value. -* Input : None. -* Output : None. -* Return : ISTR register Value -*******************************************************************************/ -u16 GetISTR(void) -{ - return(_GetISTR()); -} - -/******************************************************************************* -* Function Name : GetFNR -* Description : Returns the FNR register value. -* Input : None. -* Output : None. -* Return : FNR register Value -*******************************************************************************/ -u16 GetFNR(void) -{ - return(_GetFNR()); -} - -/******************************************************************************* -* Function Name : SetDADDR -* Description : Set the DADDR register value. -* Input : wRegValue: new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetDADDR(u16 wRegValue) -{ - _SetDADDR(wRegValue); -} - -/******************************************************************************* -* Function Name : GetDADDR -* Description : Returns the DADDR register value. -* Input : None. -* Output : None. -* Return : DADDR register Value -*******************************************************************************/ -u16 GetDADDR(void) -{ - return(_GetDADDR()); -} - -/******************************************************************************* -* Function Name : SetBTABLE -* Description : Set the BTABLE. -* Input : wRegValue: New register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetBTABLE(u16 wRegValue) -{ - _SetBTABLE(wRegValue); -} - -/******************************************************************************* -* Function Name : GetBTABLE. -* Description : Returns the BTABLE register value. -* Input : None. -* Output : None. -* Return : BTABLE address. -*******************************************************************************/ -u16 GetBTABLE(void) -{ - return(_GetBTABLE()); -} - -/******************************************************************************* -* Function Name : SetENDPOINT -* Description : Setthe Endpoint register value. -* Input : bEpNum: Endpoint Number. -* wRegValue. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetENDPOINT(u8 bEpNum, u16 wRegValue) -{ - _SetENDPOINT(bEpNum, wRegValue); -} - -/******************************************************************************* -* Function Name : GetENDPOINT -* Description : Return the Endpoint register value. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint register value. -*******************************************************************************/ -u16 GetENDPOINT(u8 bEpNum) -{ - return(_GetENDPOINT(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPType -* Description : sets the type in the endpoint register. -* Input : bEpNum: Endpoint Number. -* wType: type definition. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPType(u8 bEpNum, u16 wType) -{ - _SetEPType(bEpNum, wType); -} - -/******************************************************************************* -* Function Name : GetEPType -* Description : Returns the endpoint type. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Type -*******************************************************************************/ -u16 GetEPType(u8 bEpNum) -{ - return(_GetEPType(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPTxStatus -* Description : Set the status of Tx endpoint. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxStatus(u8 bEpNum, u16 wState) -{ - _SetEPTxStatus(bEpNum, wState); -} - -/******************************************************************************* -* Function Name : SetEPRxStatus -* Description : Set the status of Rx endpoint. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxStatus(u8 bEpNum, u16 wState) -{ - _SetEPRxStatus(bEpNum, wState); -} - -/******************************************************************************* -* Function Name : SetDouBleBuffEPStall -* Description : sets the status for Double Buffer Endpoint to STALL -* Input : bEpNum: Endpoint Number. -* bDir: Endpoint direction. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetDouBleBuffEPStall(u8 bEpNum, u8 bDir) -{ - u16 Endpoint_DTOG_Status; - Endpoint_DTOG_Status = GetENDPOINT(bEpNum); - if (bDir == EP_DBUF_OUT) - { /* OUT double buffered endpoint */ - _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1); - } - else if (bDir == EP_DBUF_IN) - { /* IN double buffered endpoint */ - _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1); - } -} - -/******************************************************************************* -* Function Name : GetEPTxStatus -* Description : Returns the endpoint Tx status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint TX Status -*******************************************************************************/ -u16 GetEPTxStatus(u8 bEpNum) -{ - return(_GetEPTxStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : GetEPRxStatus -* Description : Returns the endpoint Rx status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint RX Status -*******************************************************************************/ -u16 GetEPRxStatus(u8 bEpNum) -{ - return(_GetEPRxStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPTxValid -* Description : Valid the endpoint Tx Status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxValid(u8 bEpNum) -{ - _SetEPTxStatus(bEpNum, EP_TX_VALID); -} - -/******************************************************************************* -* Function Name : SetEPRxValid -* Description : Valid the endpoint Rx Status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxValid(u8 bEpNum) -{ - _SetEPRxStatus(bEpNum, EP_RX_VALID); -} - -/******************************************************************************* -* Function Name : SetEP_KIND -* Description : Clear the EP_KIND bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEP_KIND(u8 bEpNum) -{ - _SetEP_KIND(bEpNum); -} - -/******************************************************************************* -* Function Name : ClearEP_KIND -* Description : set the EP_KIND bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEP_KIND(u8 bEpNum) -{ - _ClearEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : Clear_Status_Out -* Description : Clear the Status Out of the related Endpoint -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void Clear_Status_Out(u8 bEpNum) -{ - _ClearEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : Set_Status_Out -* Description : Set the Status Out of the related Endpoint -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void Set_Status_Out(u8 bEpNum) -{ - _SetEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : SetEPDoubleBuff -* Description : Enable the double buffer feature for the endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDoubleBuff(u8 bEpNum) -{ - _SetEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : ClearEPDoubleBuff -* Description : Disable the double buffer feature for the endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEPDoubleBuff(u8 bEpNum) -{ - _ClearEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : GetTxStallStatus -* Description : Returns the Stall status of the Tx endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Tx Stall status. -*******************************************************************************/ -u16 GetTxStallStatus(u8 bEpNum) -{ - return(_GetTxStallStatus(bEpNum)); -} -/******************************************************************************* -* Function Name : GetRxStallStatus -* Description : Returns the Stall status of the Rx endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx Stall status. -*******************************************************************************/ -u16 GetRxStallStatus(u8 bEpNum) -{ - return(_GetRxStallStatus(bEpNum)); -} -/******************************************************************************* -* Function Name : ClearEP_CTR_RX -* Description : Clear the CTR_RX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEP_CTR_RX(u8 bEpNum) -{ - _ClearEP_CTR_RX(bEpNum); -} -/******************************************************************************* -* Function Name : ClearEP_CTR_TX -* Description : Clear the CTR_TX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEP_CTR_TX(u8 bEpNum) -{ - _ClearEP_CTR_TX(bEpNum); -} -/******************************************************************************* -* Function Name : ToggleDTOG_RX -* Description : Toggle the DTOG_RX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ToggleDTOG_RX(u8 bEpNum) -{ - _ToggleDTOG_RX(bEpNum); -} -/******************************************************************************* -* Function Name : ToggleDTOG_TX -* Description : Toggle the DTOG_TX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ToggleDTOG_TX(u8 bEpNum) -{ - _ToggleDTOG_TX(bEpNum); -} -/******************************************************************************* -* Function Name : ClearDTOG_RX. -* Description : Clear the DTOG_RX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearDTOG_RX(u8 bEpNum) -{ - _ClearDTOG_RX(bEpNum); -} -/******************************************************************************* -* Function Name : ClearDTOG_TX. -* Description : Clear the DTOG_TX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearDTOG_TX(u8 bEpNum) -{ - _ClearDTOG_TX(bEpNum); -} -/******************************************************************************* -* Function Name : SetEPAddress -* Description : Set the endpoint address. -* Input : bEpNum: Endpoint Number. -* bAddr: New endpoint address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPAddress(u8 bEpNum, u8 bAddr) -{ - _SetEPAddress(bEpNum, bAddr); -} -/******************************************************************************* -* Function Name : GetEPAddress -* Description : Get the endpoint address. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint address. -*******************************************************************************/ -u8 GetEPAddress(u8 bEpNum) -{ - return(_GetEPAddress(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPTxAddr -* Description : Set the endpoint Tx buffer address. -* Input : bEpNum: Endpoint Number. -* wAddr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxAddr(u8 bEpNum, u16 wAddr) -{ - _SetEPTxAddr(bEpNum, wAddr); -} -/******************************************************************************* -* Function Name : SetEPRxAddr -* Description : Set the endpoint Rx buffer address. -* Input : bEpNum: Endpoint Number. -* wAddr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxAddr(u8 bEpNum, u16 wAddr) -{ - _SetEPRxAddr(bEpNum, wAddr); -} -/******************************************************************************* -* Function Name : GetEPTxAddr -* Description : Returns the endpoint Tx buffer address. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx buffer address. -*******************************************************************************/ -u16 GetEPTxAddr(u8 bEpNum) -{ - return(_GetEPTxAddr(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPRxAddr. -* Description : Returns the endpoint Rx buffer address. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx buffer address. -*******************************************************************************/ -u16 GetEPRxAddr(u8 bEpNum) -{ - return(_GetEPRxAddr(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPTxCount. -* Description : Set the Tx count. -* Input : bEpNum: Endpoint Number. -* wCount: new count value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxCount(u8 bEpNum, u16 wCount) -{ - _SetEPTxCount(bEpNum, wCount); -} -/******************************************************************************* -* Function Name : SetEPCountRxReg. -* Description : Set the Count Rx Register value. -* Input : *pdwReg: point to the register. -* wCount: the new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPCountRxReg(u32 *pdwReg, u16 wCount) -{ - _SetEPCountRxReg(dwReg, wCount); -} -/******************************************************************************* -* Function Name : SetEPRxCount -* Description : Set the Rx count. -* Input : bEpNum: Endpoint Number. -* wCount: the new count value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxCount(u8 bEpNum, u16 wCount) -{ - _SetEPRxCount(bEpNum, wCount); -} -/******************************************************************************* -* Function Name : GetEPTxCount -* Description : Get the Tx count. -* Input : bEpNum: Endpoint Number. -* Output : None -* Return : Tx count value. -*******************************************************************************/ -u16 GetEPTxCount(u8 bEpNum) -{ - return(_GetEPTxCount(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPRxCount -* Description : Get the Rx count. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx count value. -*******************************************************************************/ -u16 GetEPRxCount(u8 bEpNum) -{ - return(_GetEPRxCount(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPDblBuffAddr -* Description : Set the addresses of the buffer 0 and 1. -* Input : bEpNum: Endpoint Number. -* wBuf0Addr: new address of buffer 0. -* wBuf1Addr: new address of buffer 1. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuffAddr(u8 bEpNum, u16 wBuf0Addr, u16 wBuf1Addr) -{ - _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr); -} -/******************************************************************************* -* Function Name : SetEPDblBuf0Addr -* Description : Set the Buffer 1 address. -* Input : bEpNum: Endpoint Number -* wBuf0Addr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf0Addr(u8 bEpNum, u16 wBuf0Addr) -{ - _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); -} -/******************************************************************************* -* Function Name : SetEPDblBuf1Addr -* Description : Set the Buffer 1 address. -* Input : bEpNum: Endpoint Number -* wBuf1Addr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf1Addr(u8 bEpNum, u16 wBuf1Addr) -{ - _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); -} -/******************************************************************************* -* Function Name : GetEPDblBuf0Addr -* Description : Returns the address of the Buffer 0. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -u16 GetEPDblBuf0Addr(u8 bEpNum) -{ - return(_GetEPDblBuf0Addr(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPDblBuf1Addr -* Description : Returns the address of the Buffer 1. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Address of the Buffer 1. -*******************************************************************************/ -u16 GetEPDblBuf1Addr(u8 bEpNum) -{ - return(_GetEPDblBuf1Addr(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPDblBuffCount -* Description : Set the number of bytes for a double Buffer -* endpoint. -* Input : bEpNum,bDir, wCount -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuffCount(u8 bEpNum, u8 bDir, u16 wCount) -{ - _SetEPDblBuffCount(bEpNum, bDir, wCount); -} -/******************************************************************************* -* Function Name : SetEPDblBuf0Count -* Description : Set the number of bytes in the buffer 0 of a double Buffer -* endpoint. -* Input : bEpNum, bDir, wCount -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf0Count(u8 bEpNum, u8 bDir, u16 wCount) -{ - _SetEPDblBuf0Count(bEpNum, bDir, wCount); -} -/******************************************************************************* -* Function Name : SetEPDblBuf1Count -* Description : Set the number of bytes in the buffer 0 of a double Buffer -* endpoint. -* Input : bEpNum, bDir, wCount -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf1Count(u8 bEpNum, u8 bDir, u16 wCount) -{ - _SetEPDblBuf1Count(bEpNum, bDir, wCount); -} -/******************************************************************************* -* Function Name : GetEPDblBuf0Count -* Description : Returns the number of byte received in the buffer 0 of a double -* Buffer endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Buffer 0 count -*******************************************************************************/ -u16 GetEPDblBuf0Count(u8 bEpNum) -{ - return(_GetEPDblBuf0Count(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPDblBuf1Count -* Description : Returns the number of data received in the buffer 1 of a double -* Buffer endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Buffer 1 count. -*******************************************************************************/ -u16 GetEPDblBuf1Count(u8 bEpNum) -{ - return(_GetEPDblBuf1Count(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPDblBufDir -* Description : gets direction of the double buffered endpoint -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : EP_DBUF_OUT, EP_DBUF_IN, -* EP_DBUF_ERR if the endpoint counter not yet programmed. -*******************************************************************************/ -EP_DBUF_DIR GetEPDblBufDir(u8 bEpNum) -{ - if ((u16)(*_pEPRxCount(bEpNum) & 0xFC00) != 0) - return(EP_DBUF_OUT); - else if (((u16)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0) - return(EP_DBUF_IN); - else - return(EP_DBUF_ERR); -} -/******************************************************************************* -* Function Name : FreeUserBuffer -* Description : free buffer used from the application realizing it to the line - toggles bit SW_BUF in the double buffered endpoint register -* Input : bEpNum, bDir -* Output : None. -* Return : None. -*******************************************************************************/ -void FreeUserBuffer(u8 bEpNum, u8 bDir) -{ - if (bDir == EP_DBUF_OUT) - { /* OUT double buffered endpoint */ - _ToggleDTOG_TX(bEpNum); - } - else if (bDir == EP_DBUF_IN) - { /* IN double buffered endpoint */ - _ToggleDTOG_RX(bEpNum); - } -} - -/******************************************************************************* -* Function Name : ToWord -* Description : merge two byte in a word. -* Input : bh: byte high, bl: bytes low. -* Output : None. -* Return : resulted word. -*******************************************************************************/ -u16 ToWord(u8 bh, u8 bl) -{ - u16 wRet; - wRet = (u16)bl | ((u16)bh << 8); - return(wRet); -} -/******************************************************************************* -* Function Name : ByteSwap -* Description : Swap two byte in a word. -* Input : wSwW: word to Swap. -* Output : None. -* Return : resulted word. -*******************************************************************************/ -u16 ByteSwap(u16 wSwW) -{ - u8 bTemp; - u16 wRet; - bTemp = (u8)(wSwW & 0xff); - wRet = (wSwW >> 8) | ((u16)bTemp << 8); - return(wRet); -} - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_regs.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_regs.h deleted file mode 100644 index b63cc5f..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_regs.h +++ /dev/null @@ -1,627 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_regs.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Interface prototype functions to USB cell registers -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_REGS_H -#define __USB_REGS_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -#if defined(__cplusplus) -extern "C" { -#endif - -typedef enum _EP_DBUF_DIR -{ - /* double buffered endpoint direction */ - EP_DBUF_ERR, - EP_DBUF_OUT, - EP_DBUF_IN -}EP_DBUF_DIR; - -/* endpoint buffer number */ -enum EP_BUF_NUM -{ - EP_NOBUF, - EP_BUF0, - EP_BUF1 -}; - -/* Exported constants --------------------------------------------------------*/ -#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */ -#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */ - -/******************************************************************************/ -/* General registers */ -/******************************************************************************/ - -/* Control register */ -#define CNTR ((volatile unsigned *)(RegBase + 0x40)) -/* Interrupt status register */ -#define ISTR ((volatile unsigned *)(RegBase + 0x44)) -/* Frame number register */ -#define FNR ((volatile unsigned *)(RegBase + 0x48)) -/* Device address register */ -#define DADDR ((volatile unsigned *)(RegBase + 0x4C)) -/* Buffer Table address register */ -#define BTABLE ((volatile unsigned *)(RegBase + 0x50)) -/******************************************************************************/ -/* Endpoint registers */ -/******************************************************************************/ -#define EP0REG ((volatile unsigned *)(RegBase)) /* endpoint 0 register address */ - -/* endpoints enumeration */ -#define ENDP0 ((u8)0) -#define ENDP1 ((u8)1) -#define ENDP2 ((u8)2) -#define ENDP3 ((u8)3) -#define ENDP4 ((u8)4) -#define ENDP5 ((u8)5) -#define ENDP6 ((u8)6) -#define ENDP7 ((u8)7) -/******************************************************************************/ -/* ISTR interrupt events */ -/******************************************************************************/ -#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ -#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ -#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */ -#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */ -#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */ -#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */ -#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */ -#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ - - -#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */ -#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ - -#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */ -#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/ -#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */ -#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */ -#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */ -#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */ -#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */ -#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */ - -/******************************************************************************/ -/* CNTR control register bits definitions */ -/******************************************************************************/ -#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */ -#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ -#define CNTR_ERRM (0x2000) /* ERRor Mask */ -#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */ -#define CNTR_SUSPM (0x0800) /* SUSPend Mask */ -#define CNTR_RESETM (0x0400) /* RESET Mask */ -#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */ -#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */ - - -#define CNTR_RESUME (0x0010) /* RESUME request */ -#define CNTR_FSUSP (0x0008) /* Force SUSPend */ -#define CNTR_LPMODE (0x0004) /* Low-power MODE */ -#define CNTR_PDWN (0x0002) /* Power DoWN */ -#define CNTR_FRES (0x0001) /* Force USB RESet */ - -/******************************************************************************/ -/* FNR Frame Number Register bit definitions */ -/******************************************************************************/ -#define FNR_RXDP (0x8000) /* status of D+ data line */ -#define FNR_RXDM (0x4000) /* status of D- data line */ -#define FNR_LCK (0x2000) /* LoCKed */ -#define FNR_LSOF (0x1800) /* Lost SOF */ -#define FNR_FN (0x07FF) /* Frame Number */ -/******************************************************************************/ -/* DADDR Device ADDRess bit definitions */ -/******************************************************************************/ -#define DADDR_EF (0x80) -#define DADDR_ADD (0x7F) -/******************************************************************************/ -/* Endpoint register */ -/******************************************************************************/ -/* bit positions */ -#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */ -#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ -#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */ -#define EP_SETUP (0x0800) /* EndPoint SETUP */ -#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ -#define EP_KIND (0x0100) /* EndPoint KIND */ -#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */ -#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ -#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */ -#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ - -/* EndPoint REGister MASK (no toggle fields) */ -#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD) - -/* EP_TYPE[1:0] EndPoint TYPE */ -#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */ -#define EP_BULK (0x0000) /* EndPoint BULK */ -#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ -#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ -#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ -#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK) - - -/* EP_KIND EndPoint KIND */ -#define EPKIND_MASK (~EP_KIND & EPREG_MASK) - -/* STAT_TX[1:0] STATus for TX transfer */ -#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ -#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ -#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ -#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ -#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ -#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ -#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK) - -/* STAT_RX[1:0] STATus for RX transfer */ -#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ -#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ -#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ -#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ -#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ -#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ -#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK) -/* Exported macro ------------------------------------------------------------*/ -/* SetCNTR */ -#define _SetCNTR(wRegValue) (*CNTR = (u16)wRegValue) - -/* SetISTR */ -#define _SetISTR(wRegValue) (*ISTR = (u16)wRegValue) - -/* SetDADDR */ -#define _SetDADDR(wRegValue) (*DADDR = (u16)wRegValue) - -/* SetBTABLE */ -#define _SetBTABLE(wRegValue)(*BTABLE = (u16)(wRegValue & 0xFFF8)) - -/* GetCNTR */ -#define _GetCNTR() ((u16) *CNTR) - -/* GetISTR */ -#define _GetISTR() ((u16) *ISTR) - -/* GetFNR */ -#define _GetFNR() ((u16) *FNR) - -/* GetDADDR */ -#define _GetDADDR() ((u16) *DADDR) - -/* GetBTABLE */ -#define _GetBTABLE() ((u16) *BTABLE) - -/* SetENDPOINT */ -#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \ - (u16)wRegValue) - -/* GetENDPOINT */ -#define _GetENDPOINT(bEpNum) ((u16)(*(EP0REG + bEpNum))) - -/******************************************************************************* -* Macro Name : SetEPType -* Description : sets the type in the endpoint register(bits EP_TYPE[1:0]) -* Input : bEpNum: Endpoint Number. -* wType -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\ - ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType))) - -/******************************************************************************* -* Macro Name : GetEPType -* Description : gets the type in the endpoint register(bits EP_TYPE[1:0]) -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Type -*******************************************************************************/ -#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD) - -/******************************************************************************* -* Macro Name : SetEPTxStatus -* Description : sets the status for tx transfer (bits STAT_TX[1:0]). -* Input : bEpNum: Endpoint Number. -* wState: new state -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxStatus(bEpNum,wState) {\ - register u16 _wRegVal; \ - _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\ - /* toggle first bit ? */ \ - if((EPTX_DTOG1 & wState)!= 0) \ - _wRegVal ^= EPTX_DTOG1; \ - /* toggle second bit ? */ \ - if((EPTX_DTOG2 & wState)!= 0) \ - _wRegVal ^= EPTX_DTOG2; \ - _SetENDPOINT(bEpNum, _wRegVal); \ - } /* _SetEPTxStatus */ - -/******************************************************************************* -* Macro Name : SetEPRxStatus -* Description : sets the status for rx transfer (bits STAT_TX[1:0]) -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPRxStatus(bEpNum,wState) {\ - register u16 _wRegVal; \ - \ - _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\ - /* toggle first bit ? */ \ - if((EPRX_DTOG1 & wState)!= 0) \ - _wRegVal ^= EPRX_DTOG1; \ - /* toggle second bit ? */ \ - if((EPRX_DTOG2 & wState)!= 0) \ - _wRegVal ^= EPRX_DTOG2; \ - _SetENDPOINT(bEpNum, _wRegVal); \ - } /* _SetEPRxStatus */ -/******************************************************************************* -* Macro Name : GetEPTxStatus / GetEPRxStatus -* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0] -* /STAT_RX[1:0]) -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : status . -*******************************************************************************/ -#define _GetEPTxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPTX_STAT) - -#define _GetEPRxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPRX_STAT) - -/******************************************************************************* -* Macro Name : SetEPTxValid / SetEPRxValid -* Description : sets directly the VALID tx/rx-status into the enpoint register -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID)) - -#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID)) - -/******************************************************************************* -* Macro Name : GetTxStallStatus / GetRxStallStatus. -* Description : checks stall condition in an endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : TRUE = endpoint in stall condition. -*******************************************************************************/ -#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \ - == EP_TX_STALL) -#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \ - == EP_RX_STALL) - -/******************************************************************************* -* Macro Name : SetEP_KIND / ClearEP_KIND. -* Description : set & clear EP_KIND bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ - (_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK)) -#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ - (_GetENDPOINT(bEpNum) & EPKIND_MASK))) - -/******************************************************************************* -* Macro Name : Set_Status_Out / Clear_Status_Out. -* Description : Sets/clears directly STATUS_OUT bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum) -#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum) - -/******************************************************************************* -* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff. -* Description : Sets/clears directly EP_KIND bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum) -#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum) - -/******************************************************************************* -* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX. -* Description : Clears bit CTR_RX / CTR_TX in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\ - _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK)) -#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\ - _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK)) - -/******************************************************************************* -* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX . -* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \ - EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) -#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \ - EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) - -/******************************************************************************* -* Macro Name : ClearDTOG_RX / ClearDTOG_TX. -* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\ - _ToggleDTOG_RX(bEpNum) -#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\ - _ToggleDTOG_TX(bEpNum) -/******************************************************************************* -* Macro Name : SetEPAddress. -* Description : Sets address in an endpoint register. -* Input : bEpNum: Endpoint Number. -* bAddr: Address. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\ - (_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr) - -/******************************************************************************* -* Macro Name : GetEPAddress. -* Description : Gets address in an endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _GetEPAddress(bEpNum) ((u8)(_GetENDPOINT(bEpNum) & EPADDR_FIELD)) - -#define _pEPTxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr)) -#define _pEPTxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr)) -#define _pEPRxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr)) -#define _pEPRxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr)) - -/******************************************************************************* -* Macro Name : SetEPTxAddr / SetEPRxAddr. -* Description : sets address of the tx/rx buffer. -* Input : bEpNum: Endpoint Number. -* wAddr: address to be set (must be word aligned). -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1)) -#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1)) - -/******************************************************************************* -* Macro Name : GetEPTxAddr / GetEPRxAddr. -* Description : Gets address of the tx/rx buffer. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : address of the buffer. -*******************************************************************************/ -#define _GetEPTxAddr(bEpNum) ((u16)*_pEPTxAddr(bEpNum)) -#define _GetEPRxAddr(bEpNum) ((u16)*_pEPRxAddr(bEpNum)) - -/******************************************************************************* -* Macro Name : SetEPCountRxReg. -* Description : Sets counter of rx buffer with no. of blocks. -* Input : pdwReg: pointer to counter. -* wCount: Counter. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _BlocksOf32(dwReg,wCount,wNBlocks) {\ - wNBlocks = wCount >> 5;\ - if((wCount & 0x1f) == 0)\ - wNBlocks--;\ - *pdwReg = (u32)((wNBlocks << 10) | 0x8000);\ - }/* _BlocksOf32 */ - -#define _BlocksOf2(dwReg,wCount,wNBlocks) {\ - wNBlocks = wCount >> 1;\ - if((wCount & 0x1) != 0)\ - wNBlocks++;\ - *pdwReg = (u32)(wNBlocks << 10);\ - }/* _BlocksOf2 */ - -#define _SetEPCountRxReg(dwReg,wCount) {\ - u16 wNBlocks;\ - if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\ - else {_BlocksOf2(dwReg,wCount,wNBlocks);}\ - }/* _SetEPCountRxReg */ - - - -#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\ - u32 *pdwReg = _pEPTxCount(bEpNum); \ - _SetEPCountRxReg(pdwReg, wCount);\ - } -/******************************************************************************* -* Macro Name : SetEPTxCount / SetEPRxCount. -* Description : sets counter for the tx/rx buffer. -* Input : bEpNum: endpoint number. -* wCount: Counter value. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount) -#define _SetEPRxCount(bEpNum,wCount) {\ - u32 *pdwReg = _pEPRxCount(bEpNum); \ - _SetEPCountRxReg(pdwReg, wCount);\ - } -/******************************************************************************* -* Macro Name : GetEPTxCount / GetEPRxCount. -* Description : gets counter of the tx buffer. -* Input : bEpNum: endpoint number. -* Output : None. -* Return : Counter value. -*******************************************************************************/ -#define _GetEPTxCount(bEpNum)((u16)(*_pEPTxCount(bEpNum)) & 0x3ff) -#define _GetEPRxCount(bEpNum)((u16)(*_pEPRxCount(bEpNum)) & 0x3ff) - -/******************************************************************************* -* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr. -* Description : Sets buffer 0/1 address in a double buffer endpoint. -* Input : bEpNum: endpoint number. -* : wBuf0Addr: buffer 0 address. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);} -#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);} - -/******************************************************************************* -* Macro Name : SetEPDblBuffAddr. -* Description : Sets addresses in a double buffer endpoint. -* Input : bEpNum: endpoint number. -* : wBuf0Addr: buffer 0 address. -* : wBuf1Addr = buffer 1 address. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \ - _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\ - _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\ - } /* _SetEPDblBuffAddr */ - -/******************************************************************************* -* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr. -* Description : Gets buffer 0/1 address of a double buffer endpoint. -* Input : bEpNum: endpoint number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum)) -#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum)) - -/******************************************************************************* -* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count. -* Description : Gets buffer 0/1 address of a double buffer endpoint. -* Input : bEpNum: endpoint number. -* : bDir: endpoint dir EP_DBUF_OUT = OUT -* EP_DBUF_IN = IN -* : wCount: Counter value -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \ - if(bDir == EP_DBUF_OUT)\ - /* OUT endpoint */ \ - {_SetEPRxDblBuf0Count(bEpNum,wCount);} \ - else if(bDir == EP_DBUF_IN)\ - /* IN endpoint */ \ - *_pEPTxCount(bEpNum) = (u32)wCount; \ - } /* SetEPDblBuf0Count*/ - -#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \ - if(bDir == EP_DBUF_OUT)\ - /* OUT endpoint */ \ - {_SetEPRxCount(bEpNum,wCount);}\ - else if(bDir == EP_DBUF_IN)\ - /* IN endpoint */\ - *_pEPRxCount(bEpNum) = (u32)wCount; \ - } /* SetEPDblBuf1Count */ - -#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\ - _SetEPDblBuf0Count(bEpNum, bDir, wCount); \ - _SetEPDblBuf1Count(bEpNum, bDir, wCount); \ - } /* _SetEPDblBuffCount */ - -/******************************************************************************* -* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count. -* Description : Gets buffer 0/1 rx/tx counter for double buffering. -* Input : bEpNum: endpoint number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum)) -#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum)) - - -/* External variables --------------------------------------------------------*/ -extern volatile u16 wIstr; /* ISTR register last read value */ - -/* Exported functions ------------------------------------------------------- */ -void SetCNTR(u16 /*wRegValue*/); -void SetISTR(u16 /*wRegValue*/); -void SetDADDR(u16 /*wRegValue*/); -void SetBTABLE(u16 /*wRegValue*/); -u16 GetCNTR(void); -u16 GetISTR(void); -u16 GetFNR(void); -u16 GetDADDR(void); -u16 GetBTABLE(void); -void SetENDPOINT(u8 /*bEpNum*/, u16 /*wRegValue*/); -u16 GetENDPOINT(u8 /*bEpNum*/); -void SetEPType(u8 /*bEpNum*/, u16 /*wType*/); -u16 GetEPType(u8 /*bEpNum*/); -void SetEPTxStatus(u8 /*bEpNum*/, u16 /*wState*/); -void SetEPRxStatus(u8 /*bEpNum*/, u16 /*wState*/); -void SetDouBleBuffEPStall(u8 /*bEpNum*/, u8 bDir); -u16 GetEPTxStatus(u8 /*bEpNum*/); -u16 GetEPRxStatus(u8 /*bEpNum*/); -void SetEPTxValid(u8 /*bEpNum*/); -void SetEPRxValid(u8 /*bEpNum*/); -u16 GetTxStallStatus(u8 /*bEpNum*/); -u16 GetRxStallStatus(u8 /*bEpNum*/); -void SetEP_KIND(u8 /*bEpNum*/); -void ClearEP_KIND(u8 /*bEpNum*/); -void Set_Status_Out(u8 /*bEpNum*/); -void Clear_Status_Out(u8 /*bEpNum*/); -void SetEPDoubleBuff(u8 /*bEpNum*/); -void ClearEPDoubleBuff(u8 /*bEpNum*/); -void ClearEP_CTR_RX(u8 /*bEpNum*/); -void ClearEP_CTR_TX(u8 /*bEpNum*/); -void ToggleDTOG_RX(u8 /*bEpNum*/); -void ToggleDTOG_TX(u8 /*bEpNum*/); -void ClearDTOG_RX(u8 /*bEpNum*/); -void ClearDTOG_TX(u8 /*bEpNum*/); -void SetEPAddress(u8 /*bEpNum*/, u8 /*bAddr*/); -u8 GetEPAddress(u8 /*bEpNum*/); -void SetEPTxAddr(u8 /*bEpNum*/, u16 /*wAddr*/); -void SetEPRxAddr(u8 /*bEpNum*/, u16 /*wAddr*/); -u16 GetEPTxAddr(u8 /*bEpNum*/); -u16 GetEPRxAddr(u8 /*bEpNum*/); -void SetEPCountRxReg(u32 * /*pdwReg*/, u16 /*wCount*/); -void SetEPTxCount(u8 /*bEpNum*/, u16 /*wCount*/); -void SetEPRxCount(u8 /*bEpNum*/, u16 /*wCount*/); -u16 GetEPTxCount(u8 /*bEpNum*/); -u16 GetEPRxCount(u8 /*bEpNum*/); -void SetEPDblBuf0Addr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/); -void SetEPDblBuf1Addr(u8 /*bEpNum*/, u16 /*wBuf1Addr*/); -void SetEPDblBuffAddr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/, u16 /*wBuf1Addr*/); -u16 GetEPDblBuf0Addr(u8 /*bEpNum*/); -u16 GetEPDblBuf1Addr(u8 /*bEpNum*/); -void SetEPDblBuffCount(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); -void SetEPDblBuf0Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); -void SetEPDblBuf1Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); -u16 GetEPDblBuf0Count(u8 /*bEpNum*/); -u16 GetEPDblBuf1Count(u8 /*bEpNum*/); -EP_DBUF_DIR GetEPDblBufDir(u8 /*bEpNum*/); -void FreeUserBuffer(u8 bEpNum/*bEpNum*/, u8 bDir); -u16 ToWord(u8, u8); -u16 ByteSwap(u16); - -#if defined(__cplusplus) -} -#endif - -#endif /* __USB_REGS_H */ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_type.h b/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_type.h deleted file mode 100644 index 34b3bf5..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_lib/usb_type.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** -* File Name : usb_type.h -* Author : MCD Application Team -* Version : V2.2.1 -* Date : 09/22/2008 -* Description : Type definitions used by the USB Library -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_TYPE_H -#define __USB_TYPE_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -#ifndef NULL -#define NULL ((void *)0) -#endif - -typedef signed long s32; -typedef signed short s16; -typedef signed char s8; - -typedef volatile signed long vs32; -typedef volatile signed short vs16; -typedef volatile signed char vs8; - -typedef unsigned long u32; -typedef unsigned short u16; -typedef unsigned char u8; - -typedef unsigned long const uc32; /* Read Only */ -typedef unsigned short const uc16; /* Read Only */ -typedef unsigned char const uc8; /* Read Only */ - -typedef volatile unsigned long vu32; -typedef volatile unsigned short vu16; -typedef volatile unsigned char vu8; - -typedef volatile unsigned long const vuc32; /* Read Only */ -typedef volatile unsigned short const vuc16; /* Read Only */ -typedef volatile unsigned char const vuc8; /* Read Only */ - - -typedef enum -{ - FALSE = 0, TRUE = !FALSE -} -USB_Bool; - -typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; - -typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState; - -typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -/* External variables --------------------------------------------------------*/ - -#if defined(__cplusplus) -} -#endif - -#endif /* __USB_TYPE_H */ - -/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/STM32F3/cores/maple/libmaple/usb/usb_reg_map.c b/STM32F3/cores/maple/libmaple/usb/usb_reg_map.c deleted file mode 100644 index ea60cb3..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_reg_map.c +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#include "usb_reg_map.h" - -/* TODO these could use some improvement; they're fairly - * straightforward ports of the analogous ST code. The PMA blit - * routines in particular are obvious targets for performance - * measurement and tuning. */ - -void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) { - uint16 *dst = (uint16*)usb_pma_ptr(pma_offset); - uint16 n = len >> 1; - uint16 i; - for (i = 0; i < n; i++) { - *dst = (uint16)(*buf) | *(buf + 1) << 8; - buf += 2; - dst += 2; - } - if (len & 1) { - *dst = *buf; - } -} - -void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { - uint32 *src = (uint32*)usb_pma_ptr(pma_offset); - uint16 *dst = (uint16*)buf; - uint16 n = len >> 1; - uint16 i; - for (i = 0; i < n; i++) { - *dst++ = *src++; - } - if (len & 1) { - *dst = *src & 0xFF; - } -} - -static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) { - uint16 nblocks; - if (count > 62) { - /* use 32-byte memory block size */ - nblocks = count >> 5; - if ((count & 0x1F) == 0) { - nblocks--; - } - *rxc = (nblocks << 10) | 0x8000; - } else { - /* use 2-byte memory block size */ - nblocks = count >> 1; - if ((count & 0x1) != 0) { - nblocks++; - } - *rxc = nblocks << 10; - } -} - -void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count) { - uint32 *rxc = usb_ep_rx_buf0_count_ptr(ep); - usb_set_ep_rx_count_common(rxc, count); -} - -void usb_set_ep_rx_count(uint8 ep, uint16 count) { - uint32 *rxc = usb_ep_rx_count_ptr(ep); - usb_set_ep_rx_count_common(rxc, count); -} diff --git a/STM32F3/cores/maple/libmaple/usb/usb_reg_map.h b/STM32F3/cores/maple/libmaple/usb/usb_reg_map.h deleted file mode 100644 index 2e3f6bc..0000000 --- a/STM32F3/cores/maple/libmaple/usb/usb_reg_map.h +++ /dev/null @@ -1,617 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#include -#include - -#ifndef _USB_REG_MAP_H_ -#define _USB_REG_MAP_H_ - -/* TODO: - * - Pick one of "endp", "ep" "endpt" - */ - -/* - * Register map and base pointer - */ - -#define USB_NR_EP_REGS 8 - -/** USB register map type */ -typedef struct usb_reg_map { - __io uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */ - const uint32 RESERVED[8]; /**< Reserved */ - __io uint32 CNTR; /**< Control register */ - __io uint32 ISTR; /**< Interrupt status register */ - __io uint32 FNR; /**< Frame number register */ - __io uint32 DADDR; /**< Device address */ - __io uint32 BTABLE; /**< @brief Buffer table address - * - * Address offset within the USB - * packet memory area which points - * to the base of the buffer - * descriptor table. Must be - * aligned to an 8 byte boundary. - */ -} usb_reg_map; - -/** USB register map base pointer */ -#define USB_BASE ((struct usb_reg_map*)0x40005C00) - -/* - * Register bit definitions - */ - -/* Endpoint registers (USB_EPnR) */ - -#define USB_EP_CTR_RX_BIT 15 -#define USB_EP_DTOG_RX_BIT 14 -#define USB_EP_SETUP_BIT 11 -#define USB_EP_EP_KIND_BIT 8 -#define USB_EP_CTR_TX_BIT 7 -#define USB_EP_DTOG_TX_BIT 6 - -#define USB_EP_CTR_RX BIT(USB_EP_CTR_RX_BIT) -#define USB_EP_DTOG_RX BIT(USB_EP_DTOG_RX_BIT) -#define USB_EP_STAT_RX (0x3 << 12) -#define USB_EP_STAT_RX_DISABLED (0x0 << 12) -#define USB_EP_STAT_RX_STALL (0x1 << 12) -#define USB_EP_STAT_RX_NAK (0x2 << 12) -#define USB_EP_STAT_RX_VALID (0x3 << 12) -#define USB_EP_SETUP BIT(USB_EP_SETUP_BIT) -#define USB_EP_EP_TYPE (0x3 << 9) -#define USB_EP_EP_TYPE_BULK (0x0 << 9) -#define USB_EP_EP_TYPE_CONTROL (0x1 << 9) -#define USB_EP_EP_TYPE_ISO (0x2 << 9) -#define USB_EP_EP_TYPE_INTERRUPT (0x3 << 9) -#define USB_EP_EP_KIND BIT(USB_EP_EP_KIND_BIT) -#define USB_EP_EP_KIND_DBL_BUF (0x1 << USB_EP_EP_KIND_BIT) -#define USB_EP_CTR_TX BIT(USB_EP_CTR_TX_BIT) -#define USB_EP_DTOG_TX BIT(USB_EP_DTOG_TX_BIT) -#define USB_EP_STAT_TX (0x3 << 4) -#define USB_EP_STAT_TX_DISABLED (0x0 << 4) -#define USB_EP_STAT_TX_STALL (0x1 << 4) -#define USB_EP_STAT_TX_NAK (0x2 << 4) -#define USB_EP_STAT_TX_VALID (0x3 << 4) -#define USB_EP_EA 0xF - -/* Control register (USB_CNTR) */ - -#define USB_CNTR_CTRM_BIT 15 -#define USB_CNTR_PMAOVERM_BIT 14 -#define USB_CNTR_ERRM_BIT 13 -#define USB_CNTR_WKUPM_BIT 12 -#define USB_CNTR_SUSPM_BIT 11 -#define USB_CNTR_RESETM_BIT 10 -#define USB_CNTR_SOFM_BIT 9 -#define USB_CNTR_ESOFM_BIT 8 -#define USB_CNTR_RESUME_BIT 4 -#define USB_CNTR_FSUSP_BIT 3 -#define USB_CNTR_LP_MODE_BIT 2 -#define USB_CNTR_PDWN_BIT 1 -#define USB_CNTR_FRES_BIT 0 - -#define USB_CNTR_CTRM BIT(USB_CNTR_CTRM_BIT) -#define USB_CNTR_PMAOVERM BIT(USB_CNTR_PMAOVERM_BIT) -#define USB_CNTR_ERRM BIT(USB_CNTR_ERRM_BIT) -#define USB_CNTR_WKUPM BIT(USB_CNTR_WKUPM_BIT) -#define USB_CNTR_SUSPM BIT(USB_CNTR_SUSPM_BIT) -#define USB_CNTR_RESETM BIT(USB_CNTR_RESETM_BIT) -#define USB_CNTR_SOFM BIT(USB_CNTR_SOFM_BIT) -#define USB_CNTR_ESOFM BIT(USB_CNTR_ESOFM_BIT) -#define USB_CNTR_RESUME BIT(USB_CNTR_RESUME_BIT) -#define USB_CNTR_FSUSP BIT(USB_CNTR_FSUSP_BIT) -#define USB_CNTR_LP_MODE BIT(USB_CNTR_LP_MODE_BIT) -#define USB_CNTR_PDWN BIT(USB_CNTR_PDWN_BIT) -#define USB_CNTR_FRES BIT(USB_CNTR_FRES_BIT) - -/* Interrupt status register (USB_ISTR) */ - -#define USB_ISTR_CTR_BIT 15 -#define USB_ISTR_PMAOVR_BIT 14 -#define USB_ISTR_ERR_BIT 13 -#define USB_ISTR_WKUP_BIT 12 -#define USB_ISTR_SUSP_BIT 11 -#define USB_ISTR_RESET_BIT 10 -#define USB_ISTR_SOF_BIT 9 -#define USB_ISTR_ESOF_BIT 8 -#define USB_ISTR_DIR_BIT 4 - -#define USB_ISTR_CTR BIT(USB_ISTR_CTR_BIT) -#define USB_ISTR_PMAOVR BIT(USB_ISTR_PMAOVR_BIT) -#define USB_ISTR_ERR BIT(USB_ISTR_ERR_BIT) -#define USB_ISTR_WKUP BIT(USB_ISTR_WKUP_BIT) -#define USB_ISTR_SUSP BIT(USB_ISTR_SUSP_BIT) -#define USB_ISTR_RESET BIT(USB_ISTR_RESET_BIT) -#define USB_ISTR_SOF BIT(USB_ISTR_SOF_BIT) -#define USB_ISTR_ESOF BIT(USB_ISTR_ESOF_BIT) -#define USB_ISTR_DIR BIT(USB_ISTR_DIR_BIT) -#define USB_ISTR_EP_ID 0xF - -/* Frame number register (USB_FNR) */ - -#define USB_FNR_RXDP_BIT 15 -#define USB_FNR_RXDM_BIT 14 -#define USB_FNR_LCK_BIT 13 - -#define USB_FNR_RXDP BIT(USB_FNR_RXDP_BIT) -#define USB_FNR_RXDM BIT(USB_FNR_RXDM_BIT) -#define USB_FNR_LCK BIT(USB_FNR_LCK_BIT) -#define USB_FNR_LSOF (0x3 << 11) -#define USB_FNR_FN 0x7FF - -/* Device address (USB_DADDR) */ - -#define USB_DADDR_EF_BIT 7 -#define USB_DADDR_ADD6_BIT 6 -#define USB_DADDR_ADD5_BIT 5 -#define USB_DADDR_ADD4_BIT 4 -#define USB_DADDR_ADD3_BIT 3 -#define USB_DADDR_ADD2_BIT 2 -#define USB_DADDR_ADD1_BIT 1 -#define USB_DADDR_ADD0_BIT 0 - -#define USB_DADDR_EF BIT(USB_DADDR_EF_BIT) -#define USB_DADDR_ADD6 BIT(USB_DADDR_ADD6_BIT) -#define USB_DADDR_ADD5 BIT(USB_DADDR_ADD5_BIT) -#define USB_DADDR_ADD4 BIT(USB_DADDR_ADD4_BIT) -#define USB_DADDR_ADD3 BIT(USB_DADDR_ADD3_BIT) -#define USB_DADDR_ADD2 BIT(USB_DADDR_ADD2_BIT) -#define USB_DADDR_ADD1 BIT(USB_DADDR_ADD1_BIT) -#define USB_DADDR_ADD0 BIT(USB_DADDR_ADD0_BIT) - -/* Buffer table address (USB_BTABLE) */ - -#define USB_BTABLE_BTABLE (0x1FFF << 3) - -/* - * Register convenience routines - */ - -#define __EP_CTR_NOP (USB_EP_CTR_RX | USB_EP_CTR_TX) -#define __EP_NONTOGGLE (USB_EP_CTR_RX | USB_EP_SETUP | \ - USB_EP_EP_TYPE | USB_EP_EP_KIND | \ - USB_EP_CTR_TX | USB_EP_EA) - -static inline void usb_clear_ctr_rx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - USB_BASE->EP[ep] = epr & ~USB_EP_CTR_RX & __EP_NONTOGGLE; -} - -static inline void usb_clear_ctr_tx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - USB_BASE->EP[ep] = epr & ~USB_EP_CTR_TX & __EP_NONTOGGLE; -} - -static inline uint32 usb_get_ep_dtog_tx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - return epr & USB_EP_DTOG_TX; -} - -static inline uint32 usb_get_ep_dtog_rx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - return epr & USB_EP_DTOG_RX; -} - -static inline uint32 usb_get_ep_tx_sw_buf(uint8 ep) { - return usb_get_ep_dtog_rx(ep); -} - -static inline uint32 usb_get_ep_rx_sw_buf(uint8 ep) { - return usb_get_ep_dtog_tx(ep); -} - -static inline void usb_toggle_ep_dtog_tx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - epr &= __EP_NONTOGGLE; - epr |= USB_EP_DTOG_TX; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_toggle_ep_dtog_rx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - epr &= __EP_NONTOGGLE; - epr |= USB_EP_DTOG_RX; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_clear_ep_dtog_tx(uint8 ep) { - if (usb_get_ep_dtog_tx(ep) != 0) { - usb_toggle_ep_dtog_tx(ep); - } -} - -static inline void usb_clear_ep_dtog_rx(uint8 ep) { - if (usb_get_ep_dtog_rx(ep) != 0) { - usb_toggle_ep_dtog_rx(ep); - } -} - -static inline void usb_set_ep_dtog_tx(uint8 ep) { - if (usb_get_ep_dtog_tx(ep) == 0) { - usb_toggle_ep_dtog_tx(ep); - } -} - -static inline void usb_set_ep_dtog_rx(uint8 ep) { - if (usb_get_ep_dtog_rx(ep) == 0) { - usb_toggle_ep_dtog_rx(ep); - } -} - -static inline void usb_toggle_ep_rx_sw_buf(uint8 ep) { - usb_toggle_ep_dtog_tx(ep); -} - -static inline void usb_toggle_ep_tx_sw_buf(uint8 ep) { - usb_toggle_ep_dtog_rx(ep); -} - -static inline void usb_clear_ep_rx_sw_buf(uint8 ep) { - usb_clear_ep_dtog_tx(ep); -} - -static inline void usb_clear_ep_tx_sw_buf(uint8 ep) { - usb_clear_ep_dtog_rx(ep); -} - -static inline void usb_set_ep_rx_sw_buf(uint8 ep) { - usb_set_ep_dtog_tx(ep); -} - -static inline void usb_set_ep_tx_sw_buf(uint8 ep) { - usb_set_ep_dtog_rx(ep); -} - -static inline void usb_set_ep_rx_stat(uint8 ep, uint32 status) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~(USB_EP_STAT_TX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); - epr |= __EP_CTR_NOP; - epr ^= status; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_set_ep_tx_stat(uint8 ep, uint32 status) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~(USB_EP_STAT_RX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); - epr |= __EP_CTR_NOP; - epr ^= status; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_set_ep_type(uint8 ep, uint32 type) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~USB_EP_EP_TYPE & __EP_NONTOGGLE; - epr |= type; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_set_ep_kind(uint8 ep, uint32 kind) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~USB_EP_EP_KIND & __EP_NONTOGGLE; - epr |= kind; - USB_BASE->EP[ep] = epr; -} - -static inline uint32 usb_get_ep_type(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - return epr & USB_EP_EP_TYPE; -} - -static inline uint32 usb_get_ep_kind(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - return epr & USB_EP_EP_TYPE; -} - - -static inline void usb_clear_status_out(uint8 ep) { - usb_set_ep_kind(ep, 0); -} - -/* - * Packet memory area (PMA) base pointer - */ - -/** - * @brief USB packet memory area (PMA) base pointer. - * - * The USB PMA is SRAM shared between USB and CAN. The USB peripheral - * accesses this memory directly via the packet buffer interface. */ -#define USB_PMA_BASE ((__io void*)0x40006000) - -/* - * PMA conveniences - */ - -void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset); -void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset); - -static inline void* usb_pma_ptr(uint32 offset) { - return (void*)(USB_PMA_BASE + 2 * offset); -} - -/* - * BTABLE - */ - -/* (Forward-declared) BTABLE entry. - * - * The BTABLE can be viewed as an array of usb_btable_ent values; - * these vary in structure according to the configuration of the - * endpoint. - */ -union usb_btable_ent; - -/* Bidirectional endpoint BTABLE entry */ -typedef struct usb_btable_bidi { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; -} usb_btable_bidi; - -/* Unidirectional receive-only endpoint BTABLE entry */ -typedef struct usb_btable_uni_rx { - __io uint16 empty1; const uint16 PAD1; - __io uint16 empty2; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; -} usb_btable_uni_rx; - -/* Unidirectional transmit-only endpoint BTABLE entry */ -typedef struct usb_btable_uni_tx { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 empty1; const uint16 PAD3; - __io uint16 empty2; const uint16 PAD4; -} usb_btable_uni_tx; - -/* Double-buffered transmission endpoint BTABLE entry */ -typedef struct usb_btable_dbl_tx { - __io uint16 addr_tx0; const uint16 PAD1; - __io uint16 count_tx0; const uint16 PAD2; - __io uint16 addr_tx1; const uint16 PAD3; - __io uint16 count_tx1; const uint16 PAD4; -} usb_btable_dbl_tx; - -/* Double-buffered reception endpoint BTABLE entry */ -typedef struct usb_btable_dbl_rx { - __io uint16 addr_rx0; const uint16 PAD1; - __io uint16 count_rx0; const uint16 PAD2; - __io uint16 addr_rx1; const uint16 PAD3; - __io uint16 count_rx1; const uint16 PAD4; -} usb_btable_dbl_rx; - -/* TODO isochronous endpoint entries */ - -/* Definition for above forward-declared BTABLE entry. */ -typedef union usb_btable_ent { - usb_btable_bidi bidi; - usb_btable_uni_rx u_rx; - usb_btable_uni_tx u_tx; - usb_btable_dbl_tx d_tx; - usb_btable_dbl_rx d_rx; -} usb_btable_ent; - -/* - * BTABLE conveniences - */ - -/* TODO (?) Convert usages of the many (and lengthily-named) - * accessors/mutators below to just manipulating usb_btable_entry - * values. */ - -static inline uint32* usb_btable_ptr(uint32 offset) { - return (uint32*)usb_pma_ptr(USB_BASE->BTABLE + offset); -} - -/* TX address */ - -static inline uint32* usb_ep_tx_addr_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8); -} - -static inline uint16 usb_get_ep_tx_addr(uint8 ep) { - return (uint16)*usb_ep_tx_addr_ptr(ep); -} - -static inline void usb_set_ep_tx_addr(uint8 ep, uint16 addr) { - uint32 *tx_addr = usb_ep_tx_addr_ptr(ep); - *tx_addr = addr & ~0x1; -} - -/* RX address */ - -static inline uint32* usb_ep_rx_addr_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8 + 4); -} - -static inline uint16 usb_get_ep_rx_addr(uint8 ep) { - return (uint16)*usb_ep_rx_addr_ptr(ep); -} - -static inline void usb_set_ep_rx_addr(uint8 ep, uint16 addr) { - uint32 *rx_addr = usb_ep_rx_addr_ptr(ep); - *rx_addr = addr & ~0x1; -} - -/* TX count (doesn't cover double-buffered and isochronous in) */ - -static inline uint32* usb_ep_tx_count_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8 + 2); -} - -static inline uint16 usb_get_ep_tx_count(uint8 ep) { - /* FIXME: this is broken somehow; calling it seems to - * confuse/crash the chip. */ - return (uint16)(*usb_ep_tx_count_ptr(ep) & 0x3FF); -} - -static inline void usb_set_ep_tx_count(uint8 ep, uint16 count) { - uint32 *txc = usb_ep_tx_count_ptr(ep); - *txc = count; -} - -/* RX count */ - -static inline uint32* usb_ep_rx_count_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8 + 6); -} - -static inline uint16 usb_get_ep_rx_count(uint8 ep) { - return (uint16)*usb_ep_rx_count_ptr(ep) & 0x3FF; -} - -void usb_set_ep_rx_count(uint8 ep, uint16 count); - -/* double buffer definitions */ -static inline uint32* usb_get_ep_tx_buf0_addr_ptr(uint8 ep) { - return usb_ep_tx_addr_ptr(ep); -} - -static inline uint16 usb_get_ep_tx_buf0_addr(uint8 ep) { - return usb_get_ep_tx_addr(ep); -} - -static inline void usb_set_ep_tx_buf0_addr(uint8 ep, uint16 addr) { - usb_set_ep_tx_addr(ep, addr); -} - -static inline uint32* usb_get_ep_tx_buf1_addr_ptr(uint8 ep) { - return usb_ep_rx_addr_ptr(ep); -} - -static inline uint16 usb_get_ep_tx_buf1_addr(uint8 ep) { - return usb_get_ep_rx_addr(ep); -} - -static inline void usb_set_ep_tx_buf1_addr(uint8 ep, uint16 addr) { - usb_set_ep_rx_addr(ep, addr); -} - -static inline uint32* usb_ep_tx_buf0_count_ptr(uint8 ep) { - return usb_ep_tx_count_ptr(ep); -} - -static inline uint16 usb_get_ep_tx_buf0_count(uint8 ep) { - return usb_get_ep_tx_count(ep); -} - -static inline void usb_set_ep_tx_buf0_count(uint8 ep, uint16 count) { - usb_set_ep_tx_count(ep, count); -} - -static inline uint32* usb_ep_tx_buf1_count_ptr(uint8 ep) { - return usb_ep_rx_count_ptr(ep); -} - -static inline uint16 usb_get_ep_tx_buf1_count(uint8 ep) { - return usb_get_ep_rx_count(ep); -} - -static inline void usb_set_ep_tx_buf1_count(uint8 ep, uint16 count) { - usb_set_ep_rx_count(ep, count); -} -static inline uint32* usb_get_ep_rx_buf0_addr_ptr(uint8 ep) { - return usb_ep_tx_addr_ptr(ep); -} - -static inline uint16 usb_get_ep_rx_buf0_addr(uint8 ep) { - return usb_get_ep_tx_addr(ep); -} - -static inline void usb_set_ep_rx_buf0_addr(uint8 ep, uint16 addr) { - usb_set_ep_tx_addr(ep, addr); -} - -static inline uint32* usb_get_ep_rx_buf1_addr_ptr(uint8 ep) { - return usb_ep_rx_addr_ptr(ep); -} - -static inline uint16 usb_get_ep_rx_buf1_addr(uint8 ep) { - return usb_get_ep_rx_addr(ep); -} - -static inline void usb_set_ep_rx_buf1_addr(uint8 ep, uint16 addr) { - usb_set_ep_rx_addr(ep, addr); -} - -static inline uint32* usb_ep_rx_buf0_count_ptr(uint8 ep) { - return usb_ep_tx_count_ptr(ep); -} - -static inline uint16 usb_get_ep_rx_buf0_count(uint8 ep) { - return usb_get_ep_tx_count(ep); -} - -void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count); - -static inline uint32* usb_ep_rx_buf1_count_ptr(uint8 ep) { - return usb_ep_rx_count_ptr(ep); -} - -static inline uint16 usb_get_ep_rx_buf1_count(uint8 ep) { - return usb_get_ep_rx_count(ep); -} - -static inline void usb_set_ep_rx_buf1_count(uint8 ep, uint16 count) { - usb_set_ep_rx_count(ep, count); -} - -/* - * Misc. types - */ - -typedef enum usb_ep { - USB_EP0, - USB_EP1, - USB_EP2, - USB_EP3, - USB_EP4, - USB_EP5, - USB_EP6, - USB_EP7, -} usb_ep; - -typedef enum usb_ep_type { - USB_EP_T_CTL = USB_EP_EP_TYPE_CONTROL, - USB_EP_T_BULK = USB_EP_EP_TYPE_BULK, - USB_EP_T_INT = USB_EP_EP_TYPE_INTERRUPT, - USB_EP_T_ISO = USB_EP_EP_TYPE_ISO -} usb_ep_type; - -typedef enum usb_ep_stat { - USB_EP_ST_RX_DIS = USB_EP_STAT_RX_DISABLED, - USB_EP_ST_RX_STL = USB_EP_STAT_RX_STALL, - USB_EP_ST_RX_NAK = USB_EP_STAT_RX_NAK, - USB_EP_ST_RX_VAL = USB_EP_STAT_RX_VALID, - USB_EP_ST_TX_DIS = USB_EP_STAT_TX_DISABLED, - USB_EP_ST_TX_STL = USB_EP_STAT_TX_STALL, - USB_EP_ST_TX_NAK = USB_EP_STAT_TX_NAK, - USB_EP_ST_TX_VAL = USB_EP_STAT_TX_VALID -} usb_ep_stat; - -#endif diff --git a/STM32F3/cores/maple/libmaple/util.c b/STM32F3/cores/maple/libmaple/util.c deleted file mode 100644 index 4c0b2c8..0000000 --- a/STM32F3/cores/maple/libmaple/util.c +++ /dev/null @@ -1,150 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/util.c - * @brief Utility procedures for debugging - */ - -#include -#include -#include -#include - -/* (Undocumented) hooks used by Wirish to direct our behavior here */ -extern __weak void __lm_error(void); -extern __weak usart_dev* __lm_enable_error_usart(void); - -/* If you define ERROR_LED_PORT and ERROR_LED_PIN, then a failed - * ASSERT() will also throb() an LED connected to that port and pin. - */ -#if defined(ERROR_LED_PORT) && defined(ERROR_LED_PIN) -#define HAVE_ERROR_LED -#endif - -/* (Called from exc.S with global interrupts disabled.) */ -__attribute__((noreturn)) void __error(void) { - if (__lm_error) { - __lm_error(); - } - /* Reenable global interrupts */ - nvic_globalirq_enable(); - throb(); -} - -/* - * Print an error message on a UART upon a failed assertion (if one is - * available), and punt to __error(). - * - * @param file Source file of failed assertion - * @param line Source line of failed assertion - * @param exp String representation of failed assertion - * @sideeffect Turns of all peripheral interrupts except USB. - */ -void _fail(const char* file, int line, const char* exp) { - if (__lm_enable_error_usart) { - /* Initialize the error USART */ - usart_dev *err_usart = __lm_enable_error_usart(); - - /* Print failed assert message */ - usart_putstr(err_usart, "ERROR: FAILED ASSERT("); - usart_putstr(err_usart, exp); - usart_putstr(err_usart, "): "); - usart_putstr(err_usart, file); - usart_putstr(err_usart, ": "); - usart_putudec(err_usart, line); - usart_putc(err_usart, '\n'); - usart_putc(err_usart, '\r'); - } - /* Shutdown and error fade */ - __error(); -} - -/* - * Provide an __assert_func handler to libc so that calls to assert() - * get redirected to _fail. - */ -void __assert_func(const char* file, int line, const char* method, - const char* expression) { - _fail(file, line, expression); -} - -/* - * Provide an abort() implementation that aborts execution and punts - * to __error(). - */ -void abort() { - if (__lm_enable_error_usart) { - /* Initialize the error USART */ - usart_dev *err_usart = __lm_enable_error_usart(); - /* Print abort message. */ - usart_putstr(err_usart, "ERROR: PROGRAM ABORTED VIA abort()\r\n"); - } - - /* Shutdown and error fade */ - __error(); -} - -/* This was public as of v0.0.12, so we've got to keep it public. */ -/** - * @brief Fades the error LED on and off - * @sideeffect Sets output push-pull on ERROR_LED_PIN. - */ -__attribute__((noreturn)) void throb(void) { -#ifdef HAVE_ERROR_LED - int32 slope = 1; - uint32 CC = 0x0000; - uint32 TOP_CNT = 0x0200; - uint32 i = 0; - - gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_MODE_OUTPUT); - /* Error fade. */ - while (1) { - if (CC == TOP_CNT) { - slope = -1; - } else if (CC == 0) { - slope = 1; - } - - if (i == TOP_CNT) { - CC += slope; - i = 0; - } - - if (i < CC) { - gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 1); - } else { - gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 0); - } - i++; - } -#else - /* No error LED is defined; do nothing. */ - while (1) - ; -#endif -} diff --git a/STM32F3/cores/maple/main.cpp b/STM32F3/cores/maple/main.cpp deleted file mode 100644 index 7305100..0000000 --- a/STM32F3/cores/maple/main.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -extern void setup(void); -extern void loop(void); -extern void init(void); - -// Force init to be called *first*, i.e. before static object allocation. -// Otherwise, statically allocated objects that need libmaple may fail. - __attribute__(( constructor )) void premain() { - init(); -} - -int main(void) { - setup(); - - while (1) { - loop(); - } - return 0; -} diff --git a/STM32F3/cores/maple/wirish/HardwareSPI.cpp b/STM32F3/cores/maple/wirish/HardwareSPI.cpp deleted file mode 100644 index 60d210f..0000000 --- a/STM32F3/cores/maple/wirish/HardwareSPI.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @author Marti Bolivar - * @brief Wirish SPI implementation. - */ - -#include - -#include -#include -#include - -#include -#include - -#if CYCLES_PER_MICROSECOND != 72 -/* TODO [0.2.0?] something smarter than this */ -#warning "Unexpected clock speed; SPI frequency calculation will be incorrect" -#endif - -struct spi_pins { - uint8 nss; - uint8 sck; - uint8 miso; - uint8 mosi; -}; - -static const spi_pins* dev_to_spi_pins(spi_dev *dev); - -static void enable_device(spi_dev *dev, - bool as_master, - SPIFrequency frequency, - spi_cfg_flag endianness, - spi_mode mode); - -static const spi_pins board_spi_pins[] __FLASH__ = { - {BOARD_SPI1_NSS_PIN, - BOARD_SPI1_SCK_PIN, - BOARD_SPI1_MISO_PIN, - BOARD_SPI1_MOSI_PIN}, - {BOARD_SPI2_NSS_PIN, - BOARD_SPI2_SCK_PIN, - BOARD_SPI2_MISO_PIN, - BOARD_SPI2_MOSI_PIN}, -#if defined(STM32_HIGH_DENSITY) || (STM32_MCU_SERIES == STM32_SERIES_F3) - {BOARD_SPI3_NSS_PIN, - BOARD_SPI3_SCK_PIN, - BOARD_SPI3_MISO_PIN, - BOARD_SPI3_MOSI_PIN}, -#endif -}; - - -/* - * Constructor - */ - -HardwareSPI::HardwareSPI(uint32 spi_num) { - switch (spi_num) { - case 1: - this->spi_d = SPI1; - break; - case 2: - this->spi_d = SPI2; - break; -#if defined(STM32_HIGH_DENSITY) || (STM32_MCU_SERIES == STM32_SERIES_F3) - case 3: - this->spi_d = SPI3; - break; -#endif - default: - ASSERT(0); - } -} - -/* - * Set up/tear down - */ - -void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) { - if (mode >= 4) { - ASSERT(0); - return; - } - spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; - spi_mode m = (spi_mode)mode; - enable_device(this->spi_d, true, frequency, end, m); -} - -void HardwareSPI::begin(void) { - this->begin(SPI_1_125MHZ, MSBFIRST, 0); -} - -void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) { - if (mode >= 4) { - ASSERT(0); - return; - } - spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; - spi_mode m = (spi_mode)mode; - enable_device(this->spi_d, false, (SPIFrequency)0, end, m); -} - -void HardwareSPI::beginSlave(void) { - this->beginSlave(MSBFIRST, 0); -} - -void HardwareSPI::end(void) { - if (!spi_is_enabled(this->spi_d)) { - return; - } - - // Follows RM0008's sequence for disabling a SPI in master/slave - // full duplex mode. - while (spi_is_rx_nonempty(this->spi_d)) { - // FIXME [0.1.0] remove this once you have an interrupt based driver - volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); - } - while (!spi_is_tx_empty(this->spi_d)) - ; - while (spi_is_busy(this->spi_d)) - ; - spi_peripheral_disable(this->spi_d); -} - -/* - * I/O - */ - -uint8 HardwareSPI::read(void) { - uint8 buf[1]; - this->read(buf, 1); - return buf[0]; -} - -void HardwareSPI::read(uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (rxed < len) { - while (!spi_is_rx_nonempty(this->spi_d)) - ; - buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); - } -} - -void HardwareSPI::write(uint8 byte) { - this->write(&byte, 1); -} - -void HardwareSPI::write(const uint8 *data, uint32 length) { - uint32 txed = 0; - while (txed < length) { - txed += spi_tx(this->spi_d, data + txed, length - txed); - } -} - -uint8 HardwareSPI::transfer(uint8 byte) { - this->write(byte); - return this->read(); -} - -/* - * Pin accessors - */ - -uint8 HardwareSPI::misoPin(void) { - return dev_to_spi_pins(this->spi_d)->miso; -} - -uint8 HardwareSPI::mosiPin(void) { - return dev_to_spi_pins(this->spi_d)->mosi; -} - -uint8 HardwareSPI::sckPin(void) { - return dev_to_spi_pins(this->spi_d)->sck; -} - -uint8 HardwareSPI::nssPin(void) { - return dev_to_spi_pins(this->spi_d)->nss; -} - -/* - * Deprecated functions - */ - -uint8 HardwareSPI::send(uint8 data) { - uint8 buf[] = {data}; - return this->send(buf, 1); -} - -uint8 HardwareSPI::send(uint8 *buf, uint32 len) { - uint32 txed = 0; - uint8 ret = 0; - while (txed < len) { - this->write(buf[txed++]); - ret = this->read(); - } - return ret; -} - -uint8 HardwareSPI::recv(void) { - return this->read(); -} - -/* - * Auxiliary functions - */ - -static void configure_gpios(spi_dev *dev, bool as_master); -static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq); - -static const spi_pins* dev_to_spi_pins(spi_dev *dev) { - switch (dev->clk_id) { - case RCC_SPI1: return board_spi_pins; - case RCC_SPI2: return board_spi_pins + 1; -#if defined(STM32_HIGH_DENSITY) || (STM32_MCU_SERIES == STM32_SERIES_F3) - case RCC_SPI3: return board_spi_pins + 2; -#endif - default: return NULL; - } -} - -/* Enables the device in master or slave full duplex mode. If you - * change this code, you must ensure that appropriate changes are made - * to HardwareSPI::end(). */ -static void enable_device(spi_dev *dev, - bool as_master, - SPIFrequency freq, - spi_cfg_flag endianness, - spi_mode mode) { - spi_baud_rate baud = determine_baud_rate(dev, freq); - uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE | - (as_master ? SPI_SOFT_SS : 0)); - - spi_init(dev); - configure_gpios(dev, as_master); - if (as_master) { - spi_master_enable(dev, baud, mode, cfg_flags); - } else { - spi_slave_enable(dev, mode, cfg_flags); - } -} - -static void disable_pwm(const stm32_pin_info *i) { - if (i->timer_device) { - timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); - } -} - -static void configure_gpios(spi_dev *dev, bool as_master) { - const spi_pins *pins = dev_to_spi_pins(dev); - - if (!pins) { - return; - } - - const stm32_pin_info *nssi = &PIN_MAP[pins->nss]; - const stm32_pin_info *scki = &PIN_MAP[pins->sck]; - const stm32_pin_info *misoi = &PIN_MAP[pins->miso]; - const stm32_pin_info *mosii = &PIN_MAP[pins->mosi]; - - disable_pwm(nssi); - disable_pwm(scki); - disable_pwm(misoi); - disable_pwm(mosii); - - spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit, - scki->gpio_device, scki->gpio_bit, misoi->gpio_bit, - mosii->gpio_bit); -} - -static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = { - SPI_BAUD_PCLK_DIV_2, - SPI_BAUD_PCLK_DIV_4, - SPI_BAUD_PCLK_DIV_8, - SPI_BAUD_PCLK_DIV_16, - SPI_BAUD_PCLK_DIV_32, - SPI_BAUD_PCLK_DIV_64, - SPI_BAUD_PCLK_DIV_128, - SPI_BAUD_PCLK_DIV_256, -}; - -/* - * Note: This assumes you're on a LeafLabs-style board - * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). - */ -static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) { - if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) { - /* APB2 peripherals are too fast for 140.625 KHz */ - ASSERT(0); - return (spi_baud_rate)~0; - } - return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ? - baud_rates[freq + 1] : - baud_rates[freq]); -} diff --git a/STM32F3/cores/maple/wirish/HardwareSPI.h b/STM32F3/cores/maple/wirish/HardwareSPI.h deleted file mode 100644 index 4b61b58..0000000 --- a/STM32F3/cores/maple/wirish/HardwareSPI.h +++ /dev/null @@ -1,225 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/HardwareSPI.h - * @brief High-level SPI interface - * - * This is a "bare essentials" polling driver for now. - */ - -/* TODO [0.1.0] Remove deprecated methods. */ - -#include -#include - -#include - -#ifndef _WIRISH_HARDWARESPI_H_ -#define _WIRISH_HARDWARESPI_H_ - -/** - * @brief Defines the possible SPI communication speeds. - */ -typedef enum SPIFrequency { - SPI_18MHZ = 0, /**< 18 MHz */ - SPI_9MHZ = 1, /**< 9 MHz */ - SPI_4_5MHZ = 2, /**< 4.5 MHz */ - SPI_2_25MHZ = 3, /**< 2.25 MHz */ - SPI_1_125MHZ = 4, /**< 1.125 MHz */ - SPI_562_500KHZ = 5, /**< 562.500 KHz */ - SPI_281_250KHZ = 6, /**< 281.250 KHz */ - SPI_140_625KHZ = 7, /**< 140.625 KHz */ -} SPIFrequency; - -#define MAX_SPI_FREQS 8 - -/** - * @brief Wirish SPI interface. - * - * This implementation uses software slave management, so the caller - * is responsible for controlling the slave select line. - */ -class HardwareSPI { -public: - /** - * @param spiPortNumber Number of the SPI port to manage. - */ - HardwareSPI(uint32 spiPortNumber); - - /* - * Set up/tear down - */ - - /** - * @brief Turn on a SPI port and set its GPIO pin modes for use as master. - * - * SPI port is enabled in full duplex mode, with software slave management. - * - * @param frequency Communication frequency - * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST (big-endian) - * @param mode SPI mode to use, one of SPI_MODE_0, SPI_MODE_1, - * SPI_MODE_2, and SPI_MODE_3. - */ - void begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode); - - /** - * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). - */ - void begin(void); - - /** - * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave. - * - * SPI port is enabled in full duplex mode, with software slave management. - * - * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian) - * @param mode SPI mode to use - */ - void beginSlave(uint32 bitOrder, uint32 mode); - - /** - * @brief Equivalent to beginSlave(MSBFIRST, 0). - */ - void beginSlave(void); - - /** - * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged. - */ - void end(void); - - /* - * I/O - */ - - /** - * @brief Return the next unread byte. - * - * If there is no unread byte waiting, this function will block - * until one is received. - */ - uint8 read(void); - - /** - * @brief Read length bytes, storing them into buffer. - * @param buffer Buffer to store received bytes into. - * @param length Number of bytes to store in buffer. This - * function will block until the desired number of - * bytes have been read. - */ - void read(uint8 *buffer, uint32 length); - - /** - * @brief Transmit a byte. - * @param data Byte to transmit. - */ - void write(uint8 data); - - /** - * @brief Transmit multiple bytes. - * @param buffer Bytes to transmit. - * @param length Number of bytes in buffer to transmit. - */ - void write(const uint8 *buffer, uint32 length); - - /** - * @brief Transmit a byte, then return the next unread byte. - * - * This function transmits before receiving. - * - * @param data Byte to transmit. - * @return Next unread byte. - */ - uint8 transfer(uint8 data); - - /* - * Pin accessors - */ - - /** - * @brief Return the number of the MISO (master in, slave out) pin - */ - uint8 misoPin(void); - - /** - * @brief Return the number of the MOSI (master out, slave in) pin - */ - uint8 mosiPin(void); - - /** - * @brief Return the number of the SCK (serial clock) pin - */ - uint8 sckPin(void); - - /** - * @brief Return the number of the NSS (slave select) pin - */ - uint8 nssPin(void); - - /* Escape hatch */ - - /** - * @brief Get a pointer to the underlying libmaple spi_dev for - * this HardwareSPI instance. - */ - spi_dev* c_dev(void) { return this->spi_d; } - - /* -- The following methods are deprecated --------------------------- */ - - /** - * @brief Deprecated. - * - * Use HardwareSPI::transfer() instead. - * - * @see HardwareSPI::transfer() - */ - uint8 send(uint8 data); - - /** - * @brief Deprecated. - * - * Use HardwareSPI::write() in combination with - * HardwareSPI::read() (or HardwareSPI::transfer()) instead. - * - * @see HardwareSPI::write() - * @see HardwareSPI::read() - * @see HardwareSPI::transfer() - */ - uint8 send(uint8 *data, uint32 length); - - /** - * @brief Deprecated. - * - * Use HardwareSPI::read() instead. - * - * @see HardwareSPI::read() - */ - uint8 recv(void); -private: - spi_dev *spi_d; -}; - -#endif diff --git a/STM32F3/cores/maple/wirish/HardwareSerial.cpp b/STM32F3/cores/maple/wirish/HardwareSerial.cpp deleted file mode 100644 index 87f80d1..0000000 --- a/STM32F3/cores/maple/wirish/HardwareSerial.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/HardwareSerial.cpp - * @brief Wirish serial port implementation. - */ - -#include - -#include -#include -#include -#include - -#define DEFINE_HWSERIAL(name, n) \ - HardwareSerial name(USART##n, \ - BOARD_USART##n##_TX_PIN, \ - BOARD_USART##n##_RX_PIN) - -#if BOARD_HAVE_USART1 -DEFINE_HWSERIAL(Serial1, 1); -#endif -#if BOARD_HAVE_USART2 -DEFINE_HWSERIAL(Serial2, 2); -#endif -#if BOARD_HAVE_USART3 -DEFINE_HWSERIAL(Serial3, 3); -#endif -#if BOARD_HAVE_UART4 -DEFINE_HWSERIAL(Serial4, 4); -#endif -#if BOARD_HAVE_UART5 -DEFINE_HWSERIAL(Serial5, 5); -#endif -#if BOARD_HAVE_USART6 -DEFINE_HWSERIAL(Serial6, 6); -#endif - -HardwareSerial::HardwareSerial(usart_dev *usart_device, - uint8 tx_pin, - uint8 rx_pin) { - this->usart_device = usart_device; - this->tx_pin = tx_pin; - this->rx_pin = rx_pin; -} - -/* - * Set up/tear down - */ - -#if STM32_MCU_SERIES == STM32_SERIES_F1 -/* F1 MCUs have no GPIO_AFR[HL], so turn off PWM if there's a conflict - * on this GPIO bit. */ -static void disable_timer_if_necessary(timer_dev *dev, uint8 ch) { - if (dev != NULL) { - timer_set_mode(dev, ch, TIMER_DISABLED); - } -} -#elif (STM32_MCU_SERIES == STM32_SERIES_F2) || \ - (STM32_MCU_SERIES == STM32_SERIES_F3) || \ - (STM32_MCU_SERIES == STM32_SERIES_F4) -#define disable_timer_if_necessary(dev, ch) ((void)0) -#else -#warning "Unsupported STM32 series; timer conflicts are possible" -#endif - -void HardwareSerial::begin(uint32 baud) { - ASSERT(baud <= this->usart_device->max_baud); - - if (baud > this->usart_device->max_baud) { - return; - } - - const stm32_pin_info *txi = &PIN_MAP[this->tx_pin]; - const stm32_pin_info *rxi = &PIN_MAP[this->rx_pin]; - - disable_timer_if_necessary(txi->timer_device, txi->timer_channel); - - usart_config_gpios_async(this->usart_device, - rxi->gpio_device, rxi->gpio_bit, - txi->gpio_device, txi->gpio_bit, - 0); - usart_init(this->usart_device); - usart_set_baud_rate(this->usart_device, USART_USE_PCLK, baud); - usart_enable(this->usart_device); -} - -void HardwareSerial::end(void) { - usart_disable(this->usart_device); -} - -/* - * I/O - */ - -int HardwareSerial::read(void) { - if(usart_data_available(usart_device) > 0) { - return usart_getc(usart_device); - } else { - return -1; - } -} - -uint32 HardwareSerial::available(void) { - return usart_data_available(this->usart_device); -} - -void HardwareSerial::write(unsigned char ch) { - usart_putc(this->usart_device, ch); -} - -void HardwareSerial::flush(void) { - usart_reset_rx(this->usart_device); -} diff --git a/STM32F3/cores/maple/wirish/HardwareSerial.h b/STM32F3/cores/maple/wirish/HardwareSerial.h deleted file mode 100644 index 260a99e..0000000 --- a/STM32F3/cores/maple/wirish/HardwareSerial.h +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/HardwareSerial.h - * @brief Wirish serial port interface. - */ - -#ifndef _WIRISH_HARDWARESERIAL_H_ -#define _WIRISH_HARDWARESERIAL_H_ - -#include - -#include -#include - -/* - * IMPORTANT: - * - * This class documented "by hand" (i.e., not using Doxygen) in the - * leaflabs-docs/ repository. - * - * If you alter the public HardwareSerial interface, you MUST update - * the documentation accordingly. - */ - -struct usart_dev; - -class HardwareSerial : public Print { -public: - HardwareSerial(struct usart_dev *usart_device, - uint8 tx_pin, - uint8 rx_pin); - - /* Set up/tear down */ - void begin(uint32 baud); - void end(void); - - /* I/O */ - uint32 available(void); - int read(void); - void flush(void); - virtual void write(unsigned char); - using Print::write; - - /* Pin accessors */ - int txPin(void) { return this->tx_pin; } - int rxPin(void) { return this->rx_pin; } - - /* Escape hatch into libmaple */ - /* FIXME [0.0.13] documentation */ - struct usart_dev* c_dev(void) { return this->usart_device; } -private: - struct usart_dev *usart_device; - uint8 tx_pin; - uint8 rx_pin; -}; - -#if BOARD_HAVE_USART1 -extern HardwareSerial Serial1; -#endif -#if BOARD_HAVE_USART2 -extern HardwareSerial Serial2; -#endif -#if BOARD_HAVE_USART3 -extern HardwareSerial Serial3; -#endif -#if BOARD_HAVE_UART4 -extern HardwareSerial Serial4; -#endif -#if BOARD_HAVE_UART5 -extern HardwareSerial Serial5; -#endif -#if BOARD_HAVE_USART6 -extern HardwareSerial Serial6; -#endif - -#endif diff --git a/STM32F3/cores/maple/wirish/HardwareTimer.cpp b/STM32F3/cores/maple/wirish/HardwareTimer.cpp deleted file mode 100644 index 4f68ad7..0000000 --- a/STM32F3/cores/maple/wirish/HardwareTimer.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Bryan Newbold. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#include - -#include -#include // for noInterrupts(), interrupts() -#include -#include // for CYCLES_PER_MICROSECOND - -// TODO [0.1.0] Remove deprecated pieces - -/* - * Evil hack to infer this->dev from timerNum in the HardwareTimer - * constructor. See: - * - * http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2 - * http://yosefk.com/c++fqa/function.html#fqa-33.2 - */ - -extern "C" { - static timer_dev **this_devp; - static rcc_clk_id this_id; - static void set_this_dev(timer_dev *dev) { - if (dev->clk_id == this_id) { - *this_devp = dev; - } - } -} - -/* - * HardwareTimer routines - */ - -HardwareTimer::HardwareTimer(uint8 timerNum) { - rcc_clk_id timerID = (rcc_clk_id)(RCC_TIMER1 + (timerNum - 1)); - this->dev = NULL; - noInterrupts(); // Hack to ensure we're the only ones using - // set_this_dev() and friends. TODO: use a lock. - this_id = timerID; - this_devp = &this->dev; - timer_foreach(set_this_dev); - interrupts(); - ASSERT(this->dev != NULL); -} - -void HardwareTimer::pause(void) { - timer_pause(this->dev); -} - -void HardwareTimer::resume(void) { - timer_resume(this->dev); -} - -uint32 HardwareTimer::getPrescaleFactor(void) { - return timer_get_prescaler(this->dev) + 1; -} - -void HardwareTimer::setPrescaleFactor(uint32 factor) { - timer_set_prescaler(this->dev, (uint16)(factor - 1)); -} - -uint16 HardwareTimer::getOverflow() { - return timer_get_reload(this->dev); -} - -void HardwareTimer::setOverflow(uint16 val) { - timer_set_reload(this->dev, val); -} - -uint16 HardwareTimer::getCount(void) { - return timer_get_count(this->dev); -} - -void HardwareTimer::setCount(uint16 val) { - uint16 ovf = this->getOverflow(); - timer_set_count(this->dev, min(val, ovf)); -} - -#define MAX_RELOAD ((1 << 16) - 1) -uint16 HardwareTimer::setPeriod(uint32 microseconds) { - // Not the best way to handle this edge case? - if (!microseconds) { - this->setPrescaleFactor(1); - this->setOverflow(1); - return this->getOverflow(); - } - - uint32 period_cyc = microseconds * CYCLES_PER_MICROSECOND; - uint16 prescaler = (uint16)(period_cyc / MAX_RELOAD + 1); - uint16 overflow = (uint16)((period_cyc + (prescaler / 2)) / prescaler); - this->setPrescaleFactor(prescaler); - this->setOverflow(overflow); - return overflow; -} - -void HardwareTimer::setMode(int channel, timer_mode mode) { - timer_set_mode(this->dev, (uint8)channel, (timer_mode)mode); -} - -uint16 HardwareTimer::getCompare(int channel) { - return timer_get_compare(this->dev, (uint8)channel); -} - -void HardwareTimer::setCompare(int channel, uint16 val) { - uint16 ovf = this->getOverflow(); - timer_set_compare(this->dev, (uint8)channel, min(val, ovf)); -} - -void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) { - timer_attach_interrupt(this->dev, (uint8)channel, handler); -} - -void HardwareTimer::detachInterrupt(int channel) { - timer_detach_interrupt(this->dev, (uint8)channel); -} - -void HardwareTimer::refresh(void) { - timer_generate_update(this->dev); -} - -/* -- Deprecated predefined instances -------------------------------------- */ - -HardwareTimer Timer1(1); -HardwareTimer Timer2(2); -HardwareTimer Timer3(3); -HardwareTimer Timer4(4); -#ifdef STM32_HIGH_DENSITY -HardwareTimer Timer5(5); -HardwareTimer Timer6(6); -HardwareTimer Timer7(7); -HardwareTimer Timer8(8); -#endif diff --git a/STM32F3/cores/maple/wirish/HardwareTimer.h b/STM32F3/cores/maple/wirish/HardwareTimer.h deleted file mode 100644 index 22aa010..0000000 --- a/STM32F3/cores/maple/wirish/HardwareTimer.h +++ /dev/null @@ -1,337 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Bryan Newbold. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief Wirish timer class. - */ - -#ifndef _WIRISH_HARDWARETIMER_H_ -#define _WIRISH_HARDWARETIMER_H_ - -// TODO [0.1.0] Remove deprecated pieces, pick a better API - -#include - -/** Timer mode. */ -typedef timer_mode TimerMode; - -/** - * @brief Interface to one of the 16-bit timer peripherals. - */ -class HardwareTimer { -private: - timer_dev *dev; - -public: - /** - * @brief Construct a new HardwareTimer instance. - * @param timerNum number of the timer to control. - */ - HardwareTimer(uint8 timerNum); - - /** - * @brief Stop the counter, without affecting its configuration. - * - * @see HardwareTimer::resume() - */ - void pause(void); - - /** - * @brief Resume a paused timer, without affecting its configuration. - * - * The timer will resume counting and firing interrupts as - * appropriate. - * - * Note that there is some function call overhead associated with - * using this method, so using it in concert with - * HardwareTimer::pause() is not a robust way to align multiple - * timers to the same count value. - * - * @see HardwareTimer::pause() - */ - void resume(void); - - /** - * @brief Get the timer's prescale factor. - * @return Timer prescaler, from 1 to 65,536. - * @see HardwareTimer::setPrescaleFactor() - */ - uint32 getPrescaleFactor(); - - /** - * @brief Set the timer's prescale factor. - * - * The new value won't take effect until the next time the counter - * overflows. You can force the counter to reset using - * HardwareTimer::refresh(). - * - * @param factor The new prescale value to set, from 1 to 65,536. - * @see HardwareTimer::refresh() - */ - void setPrescaleFactor(uint32 factor); - - /** - * @brief Get the timer overflow value. - * @see HardwareTimer::setOverflow() - */ - uint16 getOverflow(); - - /** - * @brief Set the timer overflow (or "reload") value. - * - * The new value won't take effect until the next time the counter - * overflows. You can force the counter to reset using - * HardwareTimer::refresh(). - * - * @param val The new overflow value to set - * @see HardwareTimer::refresh() - */ - void setOverflow(uint16 val); - - /** - * @brief Get the current timer count. - * - * @return The timer's current count value - */ - uint16 getCount(void); - - /** - * @brief Set the current timer count. - * - * @param val The new count value to set. If this value exceeds - * the timer's overflow value, it is truncated to the - * overflow value. - */ - void setCount(uint16 val); - - /** - * @brief Set the timer's period in microseconds. - * - * Configures the prescaler and overflow values to generate a timer - * reload with a period as close to the given number of - * microseconds as possible. - * - * @param microseconds The desired period of the timer. This must be - * greater than zero. - * @return The new overflow value. - */ - uint16 setPeriod(uint32 microseconds); - - /** - * @brief Configure a timer channel's mode. - * @param channel Timer channel, from 1 to 4 - * @param mode Mode to set - */ - void setMode(int channel, timer_mode mode); - - /** - * @brief Get the compare value for the given channel. - * @see HardwareTimer::setCompare() - */ - uint16 getCompare(int channel); - - /** - * @brief Set the compare value for the given channel. - * - * @param channel the channel whose compare to set, from 1 to 4. - * @param compare The compare value to set. If greater than this - * timer's overflow value, it will be truncated to - * the overflow value. - * - * @see timer_mode - * @see HardwareTimer::setMode() - * @see HardwareTimer::attachInterrupt() - */ - void setCompare(int channel, uint16 compare); - - /** - * @brief Attach an interrupt handler to the given channel. - * - * This interrupt handler will be called when the timer's counter - * reaches the given channel compare value. - * - * @param channel the channel to attach the ISR to, from 1 to 4. - * @param handler The ISR to attach to the given channel. - * @see voidFuncPtr - */ - void attachInterrupt(int channel, voidFuncPtr handler); - - /** - * @brief Remove the interrupt handler attached to the given - * channel, if any. - * - * The handler will no longer be called by this timer. - * - * @param channel the channel whose interrupt to detach, from 1 to 4. - * @see HardwareTimer::attachInterrupt() - */ - void detachInterrupt(int channel); - - /** - * @brief Reset the counter, and update the prescaler and overflow - * values. - * - * This will reset the counter to 0 in upcounting mode (the - * default). It will also update the timer's prescaler and - * overflow, if you have set them up to be changed using - * HardwareTimer::setPrescaleFactor() or - * HardwareTimer::setOverflow(). - * - * @see HardwareTimer::setPrescaleFactor() - * @see HardwareTimer::setOverflow() - */ - void refresh(void); - - /* Escape hatch */ - - /** - * @brief Get a pointer to the underlying libmaple timer_dev for - * this HardwareTimer instance. - */ - timer_dev* c_dev(void) { return this->dev; } - -/* -- The rest of this file is deprecated. --------------------------------- */ - - /** @brief Deprecated; use setMode(channel, mode) instead. */ - void setChannelMode(int channel, timer_mode mode) { - setMode(channel, mode); - } - - /** @brief Deprecated; use setMode(TIMER_CH1, mode) instead. */ - void setChannel1Mode(timer_mode mode) { setMode(TIMER_CH1, mode); } - - /** @brief Deprecated; use setMode(TIMER_CH2, mode) instead. */ - void setChannel2Mode(timer_mode mode) { setMode(TIMER_CH2, mode); } - - /** @brief Deprecated; use setMode(TIMER_CH3, mode) instead. */ - void setChannel3Mode(timer_mode mode) { setMode(TIMER_CH3, mode); } - - /** @brief Deprecated; use setMode(TIMER_CH4, mode) instead. */ - void setChannel4Mode(timer_mode mode) { setMode(TIMER_CH4, mode); } - - /** @brief Deprecated; use return getCompare(TIMER_CH1) instead. */ - uint16 getCompare1() { return getCompare(TIMER_CH1); } - - /** @brief Deprecated; use return getCompare(TIMER_CH2) instead. */ - uint16 getCompare2() { return getCompare(TIMER_CH2); } - - /** @brief Deprecated; use return getCompare(TIMER_CH3) instead. */ - uint16 getCompare3() { return getCompare(TIMER_CH3); } - - /** @brief Deprecated; use return getCompare(TIMER_CH4) instead. */ - uint16 getCompare4() { return getCompare(TIMER_CH4); } - - /** @brief Deprecated; use setCompare(TIMER_CH1, compare) instead. */ - void setCompare1(uint16 compare) { setCompare(TIMER_CH1, compare); } - - /** @brief Deprecated; use setCompare(TIMER_CH2, compare) instead. */ - void setCompare2(uint16 compare) { setCompare(TIMER_CH2, compare); } - - /** @brief Deprecated; use setCompare(TIMER_CH3, compare) instead. */ - void setCompare3(uint16 compare) { setCompare(TIMER_CH3, compare); } - - /** @brief Deprecated; use setCompare(TIMER_CH4, compare) instead. */ - void setCompare4(uint16 compare) { setCompare(TIMER_CH4, compare); } - - /** @brief Deprecated; use attachInterrupt(TIMER_CH1, handler) instead. */ - void attachCompare1Interrupt(voidFuncPtr handler) { - attachInterrupt(TIMER_CH1, handler); - } - - /** @brief Deprecated; use attachInterrupt(TIMER_CH2, handler) instead. */ - void attachCompare2Interrupt(voidFuncPtr handler) { - attachInterrupt(TIMER_CH2, handler); - } - - /** @brief Deprecated; use attachInterrupt(TIMER_CH3, handler) instead. */ - void attachCompare3Interrupt(voidFuncPtr handler) { - attachInterrupt(TIMER_CH3, handler); - } - - /** @brief Deprecated; use attachInterrupt(TIMER_CH4, handler) instead. */ - void attachCompare4Interrupt(voidFuncPtr handler) { - attachInterrupt(TIMER_CH4, handler); - } - - /** @brief Deprecated; use detachInterrupt(TIMER_CH1) instead. */ - void detachCompare1Interrupt(void) { detachInterrupt(TIMER_CH1); } - - /** @brief Deprecated; use detachInterrupt(TIMER_CH2) instead. */ - void detachCompare2Interrupt(void) { detachInterrupt(TIMER_CH2); } - - /** @brief Deprecated; use detachInterrupt(TIMER_CH3) instead. */ - void detachCompare3Interrupt(void) { detachInterrupt(TIMER_CH3); } - - /** @brief Deprecated; use detachInterrupt(TIMER_CH4) instead. */ - void detachCompare4Interrupt(void) { detachInterrupt(TIMER_CH4); } - - /** @brief Deprecated; use refresh() instead. */ - void generateUpdate(void) { refresh(); } -}; - -/** @brief Deprecated; use TIMER_OUTPUT_COMPARE instead. */ -#define TIMER_OUTPUTCOMPARE TIMER_OUTPUT_COMPARE - -/** - * @brief Deprecated. - * - * Pre-instantiated timer. - */ -extern HardwareTimer Timer1; -/** - * @brief Deprecated. - * - * Pre-instantiated timer. - */ -extern HardwareTimer Timer2; -/** - * @brief Deprecated. - * - * Pre-instantiated timer. - */ -extern HardwareTimer Timer3; -/** - * @brief Deprecated. - * - * Pre-instantiated timer. - */ -extern HardwareTimer Timer4; -#if (STM32_MCU_SERIES == STM32_SERIES_F1) && defined(STM32_HIGH_DENSITY) -/** - * @brief Deprecated. - * - * Pre-instantiated timer. - */ -extern HardwareTimer Timer5; -/** - * @brief Deprecated. - * - * Pre-instantiated timer. - */ -extern HardwareTimer Timer8; -#endif - -#endif diff --git a/STM32F3/cores/maple/wirish/Print.cpp b/STM32F3/cores/maple/wirish/Print.cpp deleted file mode 100644 index f6bc0c6..0000000 --- a/STM32F3/cores/maple/wirish/Print.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Print.cpp - Base class that provides print() and println() - * Copyright (c) 2008 David A. Mellis. All right reserved. - * Copyright (c) 2011 LeafLabs, LLC. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * Modified 23 November 2006 by David A. Mellis - * Modified 12 April 2011 by Marti Bolivar - */ - -#include - -#include -#include - -#ifndef LLONG_MAX -/* - * Note: - * - * At time of writing (12 April 2011), the limits.h that came with the - * newlib we distributed didn't include LLONG_MAX. Because we're - * staying away from using templates (see /notes/coding_standard.rst, - * "Language Features and Compiler Extensions"), this value was - * copy-pasted from a println() of the value - * - * std::numeric_limits::max(). - */ -#define LLONG_MAX 9223372036854775807LL -#endif - -/* - * Public methods - */ - -void Print::write(const char *str) { - while (*str) { - write(*str++); - } -} - -void Print::write(const void *buffer, uint32 size) { - uint8 *ch = (uint8*)buffer; - while (size--) { - write(*ch++); - } -} - -void Print::print(uint8 b, int base) { - print((uint64)b, base); -} - -void Print::print(char c) { - write(c); -} - -void Print::print(const char str[]) { - write(str); -} - -void Print::print(int n, int base) { - print((long long)n, base); -} - -void Print::print(unsigned int n, int base) { - print((unsigned long long)n, base); -} - -void Print::print(long n, int base) { - print((long long)n, base); -} - -void Print::print(unsigned long n, int base) { - print((unsigned long long)n, base); -} - -void Print::print(long long n, int base) { - if (base == BYTE) { - write((uint8)n); - return; - } - if (n < 0) { - print('-'); - n = -n; - } - printNumber(n, base); -} - -void Print::print(unsigned long long n, int base) { - if (base == BYTE) { - write((uint8)n); - } else { - printNumber(n, base); - } -} - -void Print::print(double n, int digits) { - printFloat(n, digits); -} - -void Print::println(void) { - print('\r'); - print('\n'); -} - -void Print::println(char c) { - print(c); - println(); -} - -void Print::println(const char c[]) { - print(c); - println(); -} - -void Print::println(uint8 b, int base) { - print(b, base); - println(); -} - -void Print::println(int n, int base) { - print(n, base); - println(); -} - -void Print::println(unsigned int n, int base) { - print(n, base); - println(); -} - -void Print::println(long n, int base) { - print((long long)n, base); - println(); -} - -void Print::println(unsigned long n, int base) { - print((unsigned long long)n, base); - println(); -} - -void Print::println(long long n, int base) { - print(n, base); - println(); -} - -void Print::println(unsigned long long n, int base) { - print(n, base); - println(); -} - -void Print::println(double n, int digits) { - print(n, digits); - println(); -} - -/* - * Private methods - */ - -void Print::printNumber(unsigned long long n, uint8 base) { - unsigned char buf[CHAR_BIT * sizeof(long long)]; - unsigned long i = 0; - - if (n == 0) { - print('0'); - return; - } - - while (n > 0) { - buf[i++] = n % base; - n /= base; - } - - for (; i > 0; i--) { - print((char)(buf[i - 1] < 10 ? - '0' + buf[i - 1] : - 'A' + buf[i - 1] - 10)); - } -} - -/* According to snprintf(), - * - * nextafter((double)numeric_limits::max(), 0.0) ~= 9.22337e+18 - * - * This slightly smaller value was picked semi-arbitrarily. */ -#define LARGE_DOUBLE_TRESHOLD (9.1e18) - -/* THIS FUNCTION SHOULDN'T BE USED IF YOU NEED ACCURATE RESULTS. - * - * This implementation is meant to be simple and not occupy too much - * code size. However, printing floating point values accurately is a - * subtle task, best left to a well-tested library function. - * - * See Steele and White 2003 for more details: - * - * http://kurtstephens.com/files/p372-steele.pdf - */ -void Print::printFloat(double number, uint8 digits) { - // Hackish fail-fast behavior for large-magnitude doubles - if (abs(number) >= LARGE_DOUBLE_TRESHOLD) { - if (number < 0.0) { - print('-'); - } - print(""); - return; - } - - // Handle negative numbers - if (number < 0.0) { - print('-'); - number = -number; - } - - // Simplistic rounding strategy so that e.g. print(1.999, 2) - // prints as "2.00" - double rounding = 0.5; - for (uint8 i = 0; i < digits; i++) { - rounding /= 10.0; - } - number += rounding; - - // Extract the integer part of the number and print it - long long int_part = (long long)number; - double remainder = number - int_part; - print(int_part); - - // Print the decimal point, but only if there are digits beyond - if (digits > 0) { - print("."); - } - - // Extract digits from the remainder one at a time - while (digits-- > 0) { - remainder *= 10.0; - int to_print = (int)remainder; - print(to_print); - remainder -= to_print; - } -} diff --git a/STM32F3/cores/maple/wirish/Print.h b/STM32F3/cores/maple/wirish/Print.h deleted file mode 100644 index 5fd0b7a..0000000 --- a/STM32F3/cores/maple/wirish/Print.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Print.h - Base class that provides print() and println() - * Copyright (c) 2008 David A. Mellis. All right reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA. - * - * Modified 12 April 2011 by Marti Bolivar - */ - -#ifndef _WIRISH_PRINT_H_ -#define _WIRISH_PRINT_H_ - -#include - -enum { - BYTE = 0, - BIN = 2, - OCT = 8, - DEC = 10, - HEX = 16 -}; - -class Print { -public: - virtual void write(uint8 ch) = 0; - virtual void write(const char *str); - virtual void write(const void *buf, uint32 len); - void print(char); - void print(const char[]); - void print(uint8, int=DEC); - void print(int, int=DEC); - void print(unsigned int, int=DEC); - void print(long, int=DEC); - void print(unsigned long, int=DEC); - void print(long long, int=DEC); - void print(unsigned long long, int=DEC); - void print(double, int=2); - void println(void); - void println(char); - void println(const char[]); - void println(uint8, int=DEC); - void println(int, int=DEC); - void println(unsigned int, int=DEC); - void println(long, int=DEC); - void println(unsigned long, int=DEC); - void println(long long, int=DEC); - void println(unsigned long long, int=DEC); - void println(double, int=2); -private: - void printNumber(unsigned long long, uint8); - void printFloat(double, uint8); -}; - -#endif diff --git a/STM32F3/cores/maple/wirish/bit_constants.h b/STM32F3/cores/maple/wirish/bit_constants.h deleted file mode 100644 index 4638f76..0000000 --- a/STM32F3/cores/maple/wirish/bit_constants.h +++ /dev/null @@ -1,579 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief BIT[n] and binary literal defines, for Arduino - * compatibility. - */ - -#ifndef _WIRISH_BIT_CONSTANTS_H_ -#define _WIRISH_BIT_CONSTANTS_H_ - -#define BIT0 (1 << 0) -#define BIT1 (1 << 1) -#define BIT2 (1 << 2) -#define BIT3 (1 << 3) -#define BIT4 (1 << 4) -#define BIT5 (1 << 5) -#define BIT6 (1 << 6) -#define BIT7 (1 << 7) -#define BIT8 (1 << 8) -#define BIT9 (1 << 9) -#define BIT10 (1 << 10) -#define BIT11 (1 << 11) -#define BIT12 (1 << 12) -#define BIT13 (1 << 13) -#define BIT14 (1 << 14) -#define BIT15 (1 << 15) -#define BIT16 (1 << 16) -#define BIT17 (1 << 17) -#define BIT18 (1 << 18) -#define BIT19 (1 << 19) -#define BIT20 (1 << 20) -#define BIT21 (1 << 21) -#define BIT22 (1 << 22) -#define BIT23 (1 << 23) -#define BIT24 (1 << 24) -#define BIT25 (1 << 25) -#define BIT26 (1 << 26) -#define BIT27 (1 << 27) -#define BIT28 (1 << 28) -#define BIT29 (1 << 29) -#define BIT30 (1 << 30) -#define BIT31 (1 << 31) - -#define B0 0 -#define B00 0 -#define B000 0 -#define B0000 0 -#define B00000 0 -#define B000000 0 -#define B0000000 0 -#define B00000000 0 -#define B1 1 -#define B01 1 -#define B001 1 -#define B0001 1 -#define B00001 1 -#define B000001 1 -#define B0000001 1 -#define B00000001 1 -#define B10 2 -#define B010 2 -#define B0010 2 -#define B00010 2 -#define B000010 2 -#define B0000010 2 -#define B00000010 2 -#define B11 3 -#define B011 3 -#define B0011 3 -#define B00011 3 -#define B000011 3 -#define B0000011 3 -#define B00000011 3 -#define B100 4 -#define B0100 4 -#define B00100 4 -#define B000100 4 -#define B0000100 4 -#define B00000100 4 -#define B101 5 -#define B0101 5 -#define B00101 5 -#define B000101 5 -#define B0000101 5 -#define B00000101 5 -#define B110 6 -#define B0110 6 -#define B00110 6 -#define B000110 6 -#define B0000110 6 -#define B00000110 6 -#define B111 7 -#define B0111 7 -#define B00111 7 -#define B000111 7 -#define B0000111 7 -#define B00000111 7 -#define B1000 8 -#define B01000 8 -#define B001000 8 -#define B0001000 8 -#define B00001000 8 -#define B1001 9 -#define B01001 9 -#define B001001 9 -#define B0001001 9 -#define B00001001 9 -#define B1010 10 -#define B01010 10 -#define B001010 10 -#define B0001010 10 -#define B00001010 10 -#define B1011 11 -#define B01011 11 -#define B001011 11 -#define B0001011 11 -#define B00001011 11 -#define B1100 12 -#define B01100 12 -#define B001100 12 -#define B0001100 12 -#define B00001100 12 -#define B1101 13 -#define B01101 13 -#define B001101 13 -#define B0001101 13 -#define B00001101 13 -#define B1110 14 -#define B01110 14 -#define B001110 14 -#define B0001110 14 -#define B00001110 14 -#define B1111 15 -#define B01111 15 -#define B001111 15 -#define B0001111 15 -#define B00001111 15 -#define B10000 16 -#define B010000 16 -#define B0010000 16 -#define B00010000 16 -#define B10001 17 -#define B010001 17 -#define B0010001 17 -#define B00010001 17 -#define B10010 18 -#define B010010 18 -#define B0010010 18 -#define B00010010 18 -#define B10011 19 -#define B010011 19 -#define B0010011 19 -#define B00010011 19 -#define B10100 20 -#define B010100 20 -#define B0010100 20 -#define B00010100 20 -#define B10101 21 -#define B010101 21 -#define B0010101 21 -#define B00010101 21 -#define B10110 22 -#define B010110 22 -#define B0010110 22 -#define B00010110 22 -#define B10111 23 -#define B010111 23 -#define B0010111 23 -#define B00010111 23 -#define B11000 24 -#define B011000 24 -#define B0011000 24 -#define B00011000 24 -#define B11001 25 -#define B011001 25 -#define B0011001 25 -#define B00011001 25 -#define B11010 26 -#define B011010 26 -#define B0011010 26 -#define B00011010 26 -#define B11011 27 -#define B011011 27 -#define B0011011 27 -#define B00011011 27 -#define B11100 28 -#define B011100 28 -#define B0011100 28 -#define B00011100 28 -#define B11101 29 -#define B011101 29 -#define B0011101 29 -#define B00011101 29 -#define B11110 30 -#define B011110 30 -#define B0011110 30 -#define B00011110 30 -#define B11111 31 -#define B011111 31 -#define B0011111 31 -#define B00011111 31 -#define B100000 32 -#define B0100000 32 -#define B00100000 32 -#define B100001 33 -#define B0100001 33 -#define B00100001 33 -#define B100010 34 -#define B0100010 34 -#define B00100010 34 -#define B100011 35 -#define B0100011 35 -#define B00100011 35 -#define B100100 36 -#define B0100100 36 -#define B00100100 36 -#define B100101 37 -#define B0100101 37 -#define B00100101 37 -#define B100110 38 -#define B0100110 38 -#define B00100110 38 -#define B100111 39 -#define B0100111 39 -#define B00100111 39 -#define B101000 40 -#define B0101000 40 -#define B00101000 40 -#define B101001 41 -#define B0101001 41 -#define B00101001 41 -#define B101010 42 -#define B0101010 42 -#define B00101010 42 -#define B101011 43 -#define B0101011 43 -#define B00101011 43 -#define B101100 44 -#define B0101100 44 -#define B00101100 44 -#define B101101 45 -#define B0101101 45 -#define B00101101 45 -#define B101110 46 -#define B0101110 46 -#define B00101110 46 -#define B101111 47 -#define B0101111 47 -#define B00101111 47 -#define B110000 48 -#define B0110000 48 -#define B00110000 48 -#define B110001 49 -#define B0110001 49 -#define B00110001 49 -#define B110010 50 -#define B0110010 50 -#define B00110010 50 -#define B110011 51 -#define B0110011 51 -#define B00110011 51 -#define B110100 52 -#define B0110100 52 -#define B00110100 52 -#define B110101 53 -#define B0110101 53 -#define B00110101 53 -#define B110110 54 -#define B0110110 54 -#define B00110110 54 -#define B110111 55 -#define B0110111 55 -#define B00110111 55 -#define B111000 56 -#define B0111000 56 -#define B00111000 56 -#define B111001 57 -#define B0111001 57 -#define B00111001 57 -#define B111010 58 -#define B0111010 58 -#define B00111010 58 -#define B111011 59 -#define B0111011 59 -#define B00111011 59 -#define B111100 60 -#define B0111100 60 -#define B00111100 60 -#define B111101 61 -#define B0111101 61 -#define B00111101 61 -#define B111110 62 -#define B0111110 62 -#define B00111110 62 -#define B111111 63 -#define B0111111 63 -#define B00111111 63 -#define B1000000 64 -#define B01000000 64 -#define B1000001 65 -#define B01000001 65 -#define B1000010 66 -#define B01000010 66 -#define B1000011 67 -#define B01000011 67 -#define B1000100 68 -#define B01000100 68 -#define B1000101 69 -#define B01000101 69 -#define B1000110 70 -#define B01000110 70 -#define B1000111 71 -#define B01000111 71 -#define B1001000 72 -#define B01001000 72 -#define B1001001 73 -#define B01001001 73 -#define B1001010 74 -#define B01001010 74 -#define B1001011 75 -#define B01001011 75 -#define B1001100 76 -#define B01001100 76 -#define B1001101 77 -#define B01001101 77 -#define B1001110 78 -#define B01001110 78 -#define B1001111 79 -#define B01001111 79 -#define B1010000 80 -#define B01010000 80 -#define B1010001 81 -#define B01010001 81 -#define B1010010 82 -#define B01010010 82 -#define B1010011 83 -#define B01010011 83 -#define B1010100 84 -#define B01010100 84 -#define B1010101 85 -#define B01010101 85 -#define B1010110 86 -#define B01010110 86 -#define B1010111 87 -#define B01010111 87 -#define B1011000 88 -#define B01011000 88 -#define B1011001 89 -#define B01011001 89 -#define B1011010 90 -#define B01011010 90 -#define B1011011 91 -#define B01011011 91 -#define B1011100 92 -#define B01011100 92 -#define B1011101 93 -#define B01011101 93 -#define B1011110 94 -#define B01011110 94 -#define B1011111 95 -#define B01011111 95 -#define B1100000 96 -#define B01100000 96 -#define B1100001 97 -#define B01100001 97 -#define B1100010 98 -#define B01100010 98 -#define B1100011 99 -#define B01100011 99 -#define B1100100 100 -#define B01100100 100 -#define B1100101 101 -#define B01100101 101 -#define B1100110 102 -#define B01100110 102 -#define B1100111 103 -#define B01100111 103 -#define B1101000 104 -#define B01101000 104 -#define B1101001 105 -#define B01101001 105 -#define B1101010 106 -#define B01101010 106 -#define B1101011 107 -#define B01101011 107 -#define B1101100 108 -#define B01101100 108 -#define B1101101 109 -#define B01101101 109 -#define B1101110 110 -#define B01101110 110 -#define B1101111 111 -#define B01101111 111 -#define B1110000 112 -#define B01110000 112 -#define B1110001 113 -#define B01110001 113 -#define B1110010 114 -#define B01110010 114 -#define B1110011 115 -#define B01110011 115 -#define B1110100 116 -#define B01110100 116 -#define B1110101 117 -#define B01110101 117 -#define B1110110 118 -#define B01110110 118 -#define B1110111 119 -#define B01110111 119 -#define B1111000 120 -#define B01111000 120 -#define B1111001 121 -#define B01111001 121 -#define B1111010 122 -#define B01111010 122 -#define B1111011 123 -#define B01111011 123 -#define B1111100 124 -#define B01111100 124 -#define B1111101 125 -#define B01111101 125 -#define B1111110 126 -#define B01111110 126 -#define B1111111 127 -#define B01111111 127 -#define B10000000 128 -#define B10000001 129 -#define B10000010 130 -#define B10000011 131 -#define B10000100 132 -#define B10000101 133 -#define B10000110 134 -#define B10000111 135 -#define B10001000 136 -#define B10001001 137 -#define B10001010 138 -#define B10001011 139 -#define B10001100 140 -#define B10001101 141 -#define B10001110 142 -#define B10001111 143 -#define B10010000 144 -#define B10010001 145 -#define B10010010 146 -#define B10010011 147 -#define B10010100 148 -#define B10010101 149 -#define B10010110 150 -#define B10010111 151 -#define B10011000 152 -#define B10011001 153 -#define B10011010 154 -#define B10011011 155 -#define B10011100 156 -#define B10011101 157 -#define B10011110 158 -#define B10011111 159 -#define B10100000 160 -#define B10100001 161 -#define B10100010 162 -#define B10100011 163 -#define B10100100 164 -#define B10100101 165 -#define B10100110 166 -#define B10100111 167 -#define B10101000 168 -#define B10101001 169 -#define B10101010 170 -#define B10101011 171 -#define B10101100 172 -#define B10101101 173 -#define B10101110 174 -#define B10101111 175 -#define B10110000 176 -#define B10110001 177 -#define B10110010 178 -#define B10110011 179 -#define B10110100 180 -#define B10110101 181 -#define B10110110 182 -#define B10110111 183 -#define B10111000 184 -#define B10111001 185 -#define B10111010 186 -#define B10111011 187 -#define B10111100 188 -#define B10111101 189 -#define B10111110 190 -#define B10111111 191 -#define B11000000 192 -#define B11000001 193 -#define B11000010 194 -#define B11000011 195 -#define B11000100 196 -#define B11000101 197 -#define B11000110 198 -#define B11000111 199 -#define B11001000 200 -#define B11001001 201 -#define B11001010 202 -#define B11001011 203 -#define B11001100 204 -#define B11001101 205 -#define B11001110 206 -#define B11001111 207 -#define B11010000 208 -#define B11010001 209 -#define B11010010 210 -#define B11010011 211 -#define B11010100 212 -#define B11010101 213 -#define B11010110 214 -#define B11010111 215 -#define B11011000 216 -#define B11011001 217 -#define B11011010 218 -#define B11011011 219 -#define B11011100 220 -#define B11011101 221 -#define B11011110 222 -#define B11011111 223 -#define B11100000 224 -#define B11100001 225 -#define B11100010 226 -#define B11100011 227 -#define B11100100 228 -#define B11100101 229 -#define B11100110 230 -#define B11100111 231 -#define B11101000 232 -#define B11101001 233 -#define B11101010 234 -#define B11101011 235 -#define B11101100 236 -#define B11101101 237 -#define B11101110 238 -#define B11101111 239 -#define B11110000 240 -#define B11110001 241 -#define B11110010 242 -#define B11110011 243 -#define B11110100 244 -#define B11110101 245 -#define B11110110 246 -#define B11110111 247 -#define B11111000 248 -#define B11111001 249 -#define B11111010 250 -#define B11111011 251 -#define B11111100 252 -#define B11111101 253 -#define B11111110 254 -#define B11111111 255 - -#endif /* _BIT_CONSTANTS_H_ */ diff --git a/STM32F3/cores/maple/wirish/boards.h b/STM32F3/cores/maple/wirish/boards.h deleted file mode 100644 index 6676a02..0000000 --- a/STM32F3/cores/maple/wirish/boards.h +++ /dev/null @@ -1,173 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Bryan Newbold. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/boards.h - * @author Bryan Newbold , - * Marti Bolivar - * @brief init() and board-specific pin information. - */ - -#ifndef _WIRISH_BOARDS_H_ -#define _WIRISH_BOARDS_H_ - -#include -#include -#include - -/* Set of all possible pin names; not all boards have all these (note - * that we use the Dx convention since all of the Maple's pins are - * "digital" pins (e.g. can be used with digitalRead() and - * digitalWrite()), but not all of them are connected to ADCs. */ -enum { - D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16, - D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, - D32, D33, D34, D35, D36, D37, D38, D39, D40, D41, D42, D43, D44, D45, D46, - D47, D48, D49, D50, D51, D52, D53, D54, D55, D56, D57, D58, D59, D60, D61, - D62, D63, D64, D65, D66, D67, D68, D69, D70, D71, D72, D73, D74, D75, D76, - D77, D78, D79, D80, D81, D82, D83, D84, D85, D86, D87, D88, D89, D90, D91, - D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105, - D106, D107, D108, D109, D110, D111, }; - -/** - * @brief Maps each Maple pin to a corresponding stm32_pin_info. - * @see stm32_pin_info - */ -extern const stm32_pin_info PIN_MAP[]; - -/** - * @brief Pins capable of PWM output. - * - * Its length is BOARD_NR_PWM_PINS. - */ -extern const uint8 boardPWMPins[]; - -/** - * @brief Array of pins capable of analog input. - * - * Its length is BOARD_NR_ADC_PINS. - */ -extern const uint8 boardADCPins[]; - -/** - * @brief Pins which are connected to external hardware. - * - * For example, on Maple boards, it always at least includes - * BOARD_LED_PIN. Its length is BOARD_NR_USED_PINS. - */ -extern const uint8 boardUsedPins[]; - -/** - * @brief Generic board initialization function. - * - * This function is called before main(). It ensures that the clocks - * and peripherals are configured properly for use with wirish, then - * calls boardInit(). - * - * @see boardInit() - */ -void init(void); - -/** - * @brief Board-specific initialization function. - * - * This function is called from init() after all generic board - * initialization has been performed. Each board is required to - * define its own. - * - * @see init() - */ -extern void boardInit(void); - -/** - * @brief Test if a pin is used for a special purpose on your board. - * @param pin Pin to test - * @return true if the given pin is in boardUsedPins, and false otherwise. - * @see boardUsedPins - */ -bool boardUsesPin(uint8 pin); - -/* - * Derived and default board definitions - */ - -#define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND -#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL) - -#ifndef SYSTICK_RELOAD_VAL -#define SYSTICK_RELOAD_VAL (1000 * CYCLES_PER_MICROSECOND - 1) -#endif - -#ifndef BOARD_BUTTON_PRESSED_LEVEL -#define BOARD_BUTTON_PRESSED_LEVEL HIGH -#endif - -/** - * @brief Does the board break out a USART/UART's RX and TX pins? - * - * BOARD_HAVE_USART(n) is nonzero iff USARTn is available (n must be - * an integer literal, 1 through 6). Also see BOARD_HAVE_USART1, ..., - * BOARD_HAVE_UART4 (sic), etc. - */ -#define BOARD_HAVE_USART(n) (defined(BOARD_USART##n##_TX_PIN) && \ - defined(BOARD_USART##n##_RX_PIN)) -/** Feature test: nonzero iff the board has USART1. */ -#define BOARD_HAVE_USART1 BOARD_HAVE_USART(1) -/** Feature test: nonzero iff the board has USART2, 0 otherwise. */ -#define BOARD_HAVE_USART2 BOARD_HAVE_USART(2) -/** Feature test: nonzero iff the board has USART3, 0 otherwise. */ -#define BOARD_HAVE_USART3 BOARD_HAVE_USART(3) -/** Feature test: nonzero iff the board has UART4, 0 otherwise. */ -#define BOARD_HAVE_UART4 BOARD_HAVE_USART(4) -/** Feature test: nonzero iff the board has UART5, 0 otherwise. */ -#define BOARD_HAVE_UART5 BOARD_HAVE_USART(5) -/** Feature test: nonzero iff the board has USART6, 0 otherwise. */ -#define BOARD_HAVE_USART6 BOARD_HAVE_USART(6) - -/** - * @brief Does the board break out a SPI peripheral's pins? - * - * BOARD_HAVE_SPI(n) is nonzero iff SPIn is available (n must be an - * integer literal: 1, 2, or 3). Also see BOARD_HAVE_SPI1, - * BOARD_HAVE_SPI2, BOARD_HAVE_SPI3. */ -#define BOARD_HAVE_SPI(n) (defined(BOARD_SPI##n##_NSS_PIN) && \ - defined(BOARD_SPI##n##_SCK_PIN) && \ - defined(BOARD_SPI##n##_MISO_PIN) && \ - defined(BOARD_SPI##n##_MOSI_PIN)) -/** Feature test: nonzero iff the board has SPI1. */ -#define BOARD_HAVE_SPI1 BOARD_HAVE_SPI(1) -/** Feature test: nonzero iff the board has SPI2. */ -#define BOARD_HAVE_SPI2 BOARD_HAVE_SPI(2) -/** Feature test: nonzero iff the board has SPI3. */ -#define BOARD_HAVE_SPI3 BOARD_HAVE_SPI(3) - -/** - * @brief Feature test: nonzero iff the board has SerialUSB. - */ -#define BOARD_HAVE_SERIALUSB (defined(BOARD_USB_DISC_DEV) && \ - defined(BOARD_USB_DISC_BIT)) - -#endif diff --git a/STM32F3/cores/maple/wirish/boards_private.h b/STM32F3/cores/maple/wirish/boards_private.h deleted file mode 100644 index 49867ca..0000000 --- a/STM32F3/cores/maple/wirish/boards_private.h +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/boards_private.h - * @author Marti Bolivar - * @brief Private board support header. - * - * This file declares chip-specific variables and functions which - * determine how init() behaves. It is not part of the public Wirish - * API, and can change without notice. - */ - -#ifndef _WIRISH_BOARDS_PRIVATE_H_ -#define _WIRISH_BOARDS_PRIVATE_H_ - -#include -#include - -/* Makes the PIN_MAP rows more human-readable. */ -#define PMAP_ROW(gpio_dev, gpio_bit, timer_dev, timer_ch, adc_dev, adc_ch) \ - { gpio_dev, timer_dev, adc_dev, gpio_bit, timer_ch, adc_ch } - -namespace wirish { - namespace priv { - - /* - * Chip-specific initialization data - */ - - extern rcc_pll_cfg w_board_pll_cfg; - extern adc_prescaler w_adc_pre; - extern adc_smp_rate w_adc_smp; - - /* - * Chip-specific initialization routines and helper functions. - */ - - void board_reset_pll(void); - void board_setup_clock_prescalers(void); - void board_setup_gpio(void); - void board_setup_usb(void); - void series_init(void); - - } -} - -#endif diff --git a/STM32F3/cores/maple/wirish/cxxabi-compat.cpp b/STM32F3/cores/maple/wirish/cxxabi-compat.cpp deleted file mode 100644 index 516b112..0000000 --- a/STM32F3/cores/maple/wirish/cxxabi-compat.cpp +++ /dev/null @@ -1,6 +0,0 @@ -/* We compile with nodefaultlibs, so we need to provide an error - * handler for an empty pure virtual function */ -extern "C" void __cxa_pure_virtual(void) { - while(1) - ; -} diff --git a/STM32F3/cores/maple/wirish/ext_interrupts.cpp b/STM32F3/cores/maple/wirish/ext_interrupts.cpp deleted file mode 100644 index 1195ea9..0000000 --- a/STM32F3/cores/maple/wirish/ext_interrupts.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/ext_interrupts.cpp - * @brief Wiring-like interface for external interrupts - */ - -#include - -#include -#include - -#include - -static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode); - -void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) { - if (pin >= BOARD_NR_GPIO_PINS || !handler) { - return; - } - - exti_trigger_mode outMode = exti_out_mode(mode); - - exti_attach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit), - gpio_exti_port(PIN_MAP[pin].gpio_device), - handler, - outMode); -} - -void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg, - ExtIntTriggerMode mode) { - if (pin >= BOARD_NR_GPIO_PINS || !handler) { - return; - } - - exti_trigger_mode outMode = exti_out_mode(mode); - - exti_attach_callback((exti_num)(PIN_MAP[pin].gpio_bit), - gpio_exti_port(PIN_MAP[pin].gpio_device), - handler, - arg, - outMode); -} - -void detachInterrupt(uint8 pin) { - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - - exti_detach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit)); -} - -static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) { - switch (mode) { - case RISING: - return EXTI_RISING; - case FALLING: - return EXTI_FALLING; - case CHANGE: - return EXTI_RISING_FALLING; - } - // Can't happen - ASSERT(0); - return (exti_trigger_mode)0; -} diff --git a/STM32F3/cores/maple/wirish/ext_interrupts.h b/STM32F3/cores/maple/wirish/ext_interrupts.h deleted file mode 100644 index ce1ca03..0000000 --- a/STM32F3/cores/maple/wirish/ext_interrupts.h +++ /dev/null @@ -1,128 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/ext_interrupts.h - * @brief Wiring-like external interrupt prototypes and types. - */ - -#ifndef _WIRISH_EXT_INTERRUPTS_H_ -#define _WIRISH_EXT_INTERRUPTS_H_ - -#include -#include - -/** - * The kind of transition on an external pin which should trigger an - * interrupt. - */ -typedef enum ExtIntTriggerMode { - RISING, /**< To trigger an interrupt when the pin transitions LOW - to HIGH */ - FALLING, /**< To trigger an interrupt when the pin transitions - HIGH to LOW */ - CHANGE /**< To trigger an interrupt when the pin transitions from - LOW to HIGH or HIGH to LOW (i.e., when the pin - changes). */ -} ExtIntTriggerMode; - -/** - * @brief Registers an interrupt handler on a pin. - * - * The interrupt will be triggered on a given transition on the pin, - * as specified by the mode parameter. The handler runs in interrupt - * context. The new handler will replace whatever handler is - * currently registered for the pin, if any. - * - * @param pin Pin number - * @param handler Function to run upon external interrupt trigger. - * The handler should take no arguments, and have void - * return type. - * @param mode Type of transition to trigger on, e.g. falling, rising, etc. - * - * @sideeffect Registers a handler - * @see detachInterrupt() - */ -void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode); - -/** - * @brief Registers an interrupt handler on a pin. - * - * The interrupt will be triggered on a given transition on the pin, - * as specified by the mode parameter. The handler runs in interrupt - * context. The new handler will replace whatever handler is - * currently registered for the pin, if any. - * - * @param pin Pin number - * @param handler Static class member function to run upon external interrupt - * trigger. The handler should take 1 argument and return void - * @param arg Argument that the handler will be passed when it's called. One - * use of this is to pass the specific instance of the class that - * will handle the interrupt. - * @param mode Type of transition to trigger on, e.g. falling, rising, etc. - * - * @sideeffect Registers a handler - * @see detachInterrupt() - */ -void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg, - ExtIntTriggerMode mode); - -/** - * @brief Disable any registered external interrupt. - * @param pin Maple pin number - * @sideeffect unregisters external interrupt handler - * @see attachInterrupt() - */ -void detachInterrupt(uint8 pin); - -/** - * Re-enable interrupts. - * - * Call this after noInterrupts() to re-enable interrupt handling, - * after you have finished with a timing-critical section of code. - * - * @see noInterrupts() - */ -static __always_inline void interrupts() { - nvic_globalirq_enable(); -} - -/** - * Disable interrupts. - * - * After calling this function, all user-programmable interrupts will - * be disabled. You can call this function before a timing-critical - * section of code, then call interrupts() to re-enable interrupt - * handling. - * - * @see interrupts() - */ -static __always_inline void noInterrupts() { - nvic_globalirq_disable(); -} - -#endif - diff --git a/STM32F3/cores/maple/wirish/io.h b/STM32F3/cores/maple/wirish/io.h deleted file mode 100644 index 08bbc06..0000000 --- a/STM32F3/cores/maple/wirish/io.h +++ /dev/null @@ -1,222 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/io.h - * @brief Wiring-style pin I/O interface. - */ - -#ifndef _WIRISH_IO_H_ -#define _WIRISH_IO_H_ - -#include -#include - -/** - * Specifies a GPIO pin behavior. - * @see pinMode() - */ -typedef enum WiringPinMode { - OUTPUT, /**< Basic digital output: when the pin is HIGH, the - voltage is held at +3.3v (Vcc) and when it is LOW, it - is pulled down to ground. */ - - OUTPUT_OPEN_DRAIN, /**< In open drain mode, the pin indicates - "low" by accepting current flow to ground - and "high" by providing increased - impedance. An example use would be to - connect a pin to a bus line (which is pulled - up to a positive voltage by a separate - supply through a large resistor). When the - pin is high, not much current flows through - to ground and the line stays at positive - voltage; when the pin is low, the bus - "drains" to ground with a small amount of - current constantly flowing through the large - resistor from the external supply. In this - mode, no current is ever actually sourced - from the pin. */ - - INPUT, /**< Basic digital input. The pin voltage is sampled; when - it is closer to 3.3v (Vcc) the pin status is high, and - when it is closer to 0v (ground) it is low. If no - external circuit is pulling the pin voltage to high or - low, it will tend to randomly oscillate and be very - sensitive to noise (e.g., a breath of air across the pin - might cause the state to flip). */ - - INPUT_ANALOG, /**< This is a special mode for when the pin will be - used for analog (not digital) reads. Enables ADC - conversion to be performed on the voltage at the - pin. */ - - INPUT_PULLUP, /**< The state of the pin in this mode is reported - the same way as with INPUT, but the pin voltage - is gently "pulled up" towards +3.3v. This means - the state will be high unless an external device - is specifically pulling the pin down to ground, - in which case the "gentle" pull up will not - affect the state of the input. */ - - INPUT_PULLDOWN, /**< The state of the pin in this mode is reported - the same way as with INPUT, but the pin voltage - is gently "pulled down" towards 0v. This means - the state will be low unless an external device - is specifically pulling the pin up to 3.3v, in - which case the "gentle" pull down will not - affect the state of the input. */ - - INPUT_FLOATING, /**< Synonym for INPUT. */ - - PWM, /**< This is a special mode for when the pin will be used for - PWM output (a special case of digital output). */ - - PWM_OPEN_DRAIN, /**< Like PWM, except that instead of alternating - cycles of LOW and HIGH, the voltage on the pin - consists of alternating cycles of LOW and - floating (disconnected). */ -} WiringPinMode; - -/** - * Configure behavior of a GPIO pin. - * - * @param pin Number of pin to configure. - * @param mode Mode corresponding to desired pin behavior. - * @see WiringPinMode - */ -void pinMode(uint8 pin, WiringPinMode mode); - -#define HIGH 0x1 -#define LOW 0x0 - -/** - * Writes a (digital) value to a pin. The pin must have its - * mode set to OUTPUT or OUTPUT_OPEN_DRAIN. - * - * @param pin Pin to write to. - * @param value Either LOW (write a 0) or HIGH (write a 1). - * @see pinMode() - */ -void digitalWrite(uint8 pin, uint8 value); - -/** - * Read a digital value from a pin. The pin must have its mode set to - * one of INPUT, INPUT_PULLUP, and INPUT_PULLDOWN. - * - * @param pin Pin to read from. - * @return LOW or HIGH. - * @see pinMode() - */ -uint32 digitalRead(uint8 pin); - -/** - * Read an analog value from pin. This function blocks during ADC - * conversion, and has 12 bits of resolution. The pin must have its - * mode set to INPUT_ANALOG. - * - * @param pin Pin to read from. - * @return Converted voltage, in the range 0--4095, (i.e. a 12-bit ADC - * conversion). - * @see pinMode() - */ -uint16 analogRead(uint8 pin); - -/** - * Toggles the digital value at the given pin. - * - * The pin must have its mode set to OUTPUT. - * - * @param pin the pin to toggle. If the pin is HIGH, set it LOW. If - * it is LOW, set it HIGH. - * - * @see pinMode() - */ -void togglePin(uint8 pin); - -/** - * Toggle the LED. - * - * If the LED is on, turn it off. If it is off, turn it on. - * - * The LED must its mode set to OUTPUT. This can be accomplished - * portably over all LeafLabs boards by calling pinMode(BOARD_LED_PIN, - * OUTPUT) before calling this function. - * - * @see pinMode() - */ -static inline void toggleLED() { - togglePin(BOARD_LED_PIN); -} - -/** - * If the button is currently pressed, waits until the button is no - * longer being pressed, and returns true. Otherwise, returns false. - * - * The button pin must have its mode set to INPUT. This can be - * accomplished portably over all LeafLabs boards by calling - * pinMode(BOARD_BUTTON_PIN, INPUT). - * - * @see pinMode() - */ -uint8 isButtonPressed(uint8 pin=BOARD_BUTTON_PIN, - uint32 pressedLevel=BOARD_BUTTON_PRESSED_LEVEL); - -/** - * Wait until the button is pressed and released, timing out if no - * press occurs. - * - * The button pin must have its mode set to INPUT. This can be - * accomplished portably over all LeafLabs boards by calling - * pinMode(BOARD_BUTTON_PIN, INPUT). - * - * @param timeout_millis Number of milliseconds to wait until the - * button is pressed. If timeout_millis is left out (or 0), wait - * forever. - * - * @return true, if the button was pressed; false, if the timeout was - * reached. - * - * @see pinMode() - */ -uint8 waitForButtonPress(uint32 timeout_millis=0); - -/** - * Shift out a byte of data, one bit at a time. - * - * This function starts at either the most significant or least - * significant bit in a byte value, and shifts out each byte in order - * onto a data pin. After each bit is written to the data pin, a - * separate clock pin is pulsed to indicate that the new bit is - * available. - * - * @param dataPin Pin to shift data out on - * @param clockPin Pin to pulse after each bit is shifted out - * @param bitOrder Either MSBFIRST (big-endian) or LSBFIRST (little-endian). - * @param value Value to shift out - */ -void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value); - -#endif diff --git a/STM32F3/cores/maple/wirish/main.cxx b/STM32F3/cores/maple/wirish/main.cxx deleted file mode 100644 index 9c0b9cc..0000000 --- a/STM32F3/cores/maple/wirish/main.cxx +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -// Force init to be called *first*, i.e. before static object allocation. -// Otherwise, statically allocated objects that need libmaple may fail. - __attribute__(( constructor )) void premain() { - init(); -} - -int main(void) { - setup(); - - while (1) { - loop(); - } - return 0; -} diff --git a/STM32F3/cores/maple/wirish/pwm.cpp b/STM32F3/cores/maple/wirish/pwm.cpp deleted file mode 100644 index 44884cd..0000000 --- a/STM32F3/cores/maple/wirish/pwm.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/pwm.cpp - * @brief Wiring-style pwmWrite(). - */ - -#include - -#include -#include - -#include - -void pwmWrite(uint8 pin, uint16 duty_cycle) { - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - timer_dev *dev = PIN_MAP[pin].timer_device; - uint8 cc_channel = PIN_MAP[pin].timer_channel; - ASSERT(dev && cc_channel); - timer_set_compare(dev, cc_channel, duty_cycle); -} diff --git a/STM32F3/cores/maple/wirish/pwm.h b/STM32F3/cores/maple/wirish/pwm.h deleted file mode 100644 index 6631d42..0000000 --- a/STM32F3/cores/maple/wirish/pwm.h +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/pwm.h - * @brief Wiring-style PWM interface. - */ - -#ifndef _WIRISH_PWM_H_ -#define _WIRISH_PWM_H_ - -#include - -/** - * As a convenience, analogWrite is an alias of pwmWrite to ease - * porting Arduino code. However, period and duty will have to be - * recalibrated. - */ -#define analogWrite pwmWrite - -/** - * Set the PWM duty on the given pin. - * - * User code is expected to determine and honor the maximum value - * (based on the configured period). - * - * @param pin PWM output pin - * @param duty_cycle Duty cycle to set. - */ -void pwmWrite(uint8 pin, uint16 duty_cycle); - -#endif - diff --git a/STM32F3/cores/maple/wirish/rules.mk b/STM32F3/cores/maple/wirish/rules.mk deleted file mode 100644 index 539e966..0000000 --- a/STM32F3/cores/maple/wirish/rules.mk +++ /dev/null @@ -1,66 +0,0 @@ -# Standard things -sp := $(sp).x -dirstack_$(sp) := $(d) -d := $(dir) -BUILDDIRS += $(BUILD_PATH)/$(d) - -# Add board directory and MCU-specific directory to BUILDDIRS. These -# are in subdirectories, but they're logically part of the Wirish -# submodule. -ifeq ($(MCU_SERIES), stm32f3) -WIRISH_BOARD_PATH := boards/$(MCU_F3_LINE) -else -WIRISH_BOARD_PATH := boards/$(BOARD) -endif -BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) -BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES) - -# Safe includes for Wirish. -WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include - -# Local flags. Add -I$(d) to allow for private includes. -CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) - -# Local rules and targets -sSRCS_$(d) := start.S -cSRCS_$(d) := start_c.c -cSRCS_$(d) += syscalls.c -cSRCS_$(d) += $(MCU_SERIES)/util_hooks.c -cppSRCS_$(d) := boards.cpp -cppSRCS_$(d) += cxxabi-compat.cpp -cppSRCS_$(d) += ext_interrupts.cpp -cppSRCS_$(d) += HardwareSerial.cpp -cppSRCS_$(d) += HardwareTimer.cpp -cppSRCS_$(d) += Print.cpp -cppSRCS_$(d) += pwm.cpp -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),stm32f1 stm32f3)) # TODO port USB serial to F2 -cppSRCS_$(d) += usb_serial.cpp -cppSRCS_$(d) += HardwareSPI.cpp -endif -cppSRCS_$(d) += wirish_analog.cpp -cppSRCS_$(d) += wirish_digital.cpp -cppSRCS_$(d) += wirish_math.cpp -cppSRCS_$(d) += wirish_shift.cpp -cppSRCS_$(d) += wirish_time.cpp -cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp -cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp -cppSRCS_$(d) += $(MCU_SERIES)/wirish_debug.cpp -cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp - -sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) -cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%) - -OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ - $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \ - $(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o) -DEPS_$(d) := $(OBJS_$(d):%.o=%.d) - -$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) - -TGT_BIN += $(OBJS_$(d)) - -# Standard things --include $(DEPS_$(d)) -d := $(dirstack_$(sp)) -sp := $(basename $(sp)) diff --git a/STM32F3/cores/maple/wirish/stm32f3/f3_wirish_digital.cpp b/STM32F3/cores/maple/wirish/stm32f3/f3_wirish_digital.cpp deleted file mode 100644 index 50cda60..0000000 --- a/STM32F3/cores/maple/wirish/stm32f3/f3_wirish_digital.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/* - * STM32F3 implementations for basic GPIO functionality. - */ - -#include - -#include -#include - -#include - -void pinMode(uint8 pin, WiringPinMode w_mode) { - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - - gpio_pin_mode mode; - // People always do the silly pin-toggle speed benchmark, so let's - // accomodate them: - unsigned flags = GPIO_MODEF_SPEED_HIGH; - bool pwm = false; - switch(w_mode) { - case OUTPUT: - mode = GPIO_MODE_OUTPUT; - break; - case OUTPUT_OPEN_DRAIN: - mode = GPIO_MODE_OUTPUT; - flags |= GPIO_MODEF_TYPE_OD; - break; - case INPUT: - case INPUT_FLOATING: - mode = GPIO_MODE_INPUT; - break; - case INPUT_ANALOG: - mode = GPIO_MODE_ANALOG; - break; - case INPUT_PULLUP: - mode = GPIO_MODE_INPUT; - flags |= GPIO_MODEF_PUPD_PU; - break; - case INPUT_PULLDOWN: - mode = GPIO_MODE_INPUT; - flags |= GPIO_MODEF_PUPD_PD; - break; - case PWM: - mode = GPIO_MODE_AF; - pwm = true; - break; - case PWM_OPEN_DRAIN: - mode = GPIO_MODE_AF; - flags |= GPIO_MODEF_TYPE_OD; - pwm = true; - break; - default: - ASSERT(0); // Can't happen - return; - } - - const stm32_pin_info *info = &PIN_MAP[pin]; - - if (pwm) { - /* If enabling PWM, tell the timer to do PWM, and tell the pin - * to listen to the right timer. */ - ASSERT(info->timer_device != NULL); - if (info->timer_device == NULL) { - return; - } - gpio_af timer_af = timer_get_af(info->timer_device); - timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); - gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); - } - gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); -} diff --git a/STM32F3/cores/maple/wirish/stm32f3/util_hooks.c b/STM32F3/cores/maple/wirish/stm32f3/util_hooks.c deleted file mode 100644 index 2387cf7..0000000 --- a/STM32F3/cores/maple/wirish/stm32f3/util_hooks.c +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/* - * STM32F3 implementations for libmaple util.c hooks - * FIXME these are just minimal stubs - */ - -#include - -/* - * Disables all peripheral interrupts. Called by __error() with global - * interrupts disabled. - */ -void __lm_error(void) { - nvic_irq_disable_all(); -} - -/* - * Enable the error USART for writing. - */ -/* usart_dev* __lm_enable_error_usart(void) { (TODO) } */ diff --git a/STM32F3/cores/maple/wirish/stm32f3/wirish_debug.cpp b/STM32F3/cores/maple/wirish/stm32f3/wirish_debug.cpp deleted file mode 100644 index 6a6e1c1..0000000 --- a/STM32F3/cores/maple/wirish/stm32f3/wirish_debug.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/stm32f3/wirish_debug.cpp - * @brief High level debug port configuration - */ - -#include -#include -#include - -void disableDebugPorts(void) { - // BOARD_JTMS_SWDIO_PIN-BOARD_JTDI_PIN and BOARD_JTDO_PIN-BOARD_NJTRST_PIN are in system alternate function mode on - // reset, to support JTAG. Just put them in input mode to release - // them. - gpio_set_modef(PIN_MAP[BOARD_JTMS_SWDIO_PIN].gpio_device, PIN_MAP[BOARD_JTMS_SWDIO_PIN].gpio_bit, - GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); - gpio_set_modef(PIN_MAP[BOARD_JTCK_SWCLK_PIN].gpio_device, PIN_MAP[BOARD_JTCK_SWCLK_PIN].gpio_bit, - GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); - gpio_set_modef(PIN_MAP[BOARD_JTDI_PIN].gpio_device, PIN_MAP[BOARD_JTDI_PIN].gpio_bit, - GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); - gpio_set_modef(PIN_MAP[BOARD_JTDO_PIN].gpio_device, PIN_MAP[BOARD_JTDO_PIN].gpio_bit, - GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); - gpio_set_modef(PIN_MAP[BOARD_NJTRST_PIN].gpio_device, PIN_MAP[BOARD_NJTRST_PIN].gpio_bit, - GPIO_MODE_INPUT, GPIO_MODEF_PUPD_NONE); -} - -void enableDebugPorts(void) { - // Put BOARD_JTMS_SWDIO_PIN-BOARD_JTDI_PIN and BOARD_JTDO_PIN-BOARD_NJTRST_PIN back in system AF mode. - gpio_set_modef(PIN_MAP[BOARD_JTMS_SWDIO_PIN].gpio_device, PIN_MAP[BOARD_JTMS_SWDIO_PIN].gpio_bit, - GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(PIN_MAP[BOARD_JTCK_SWCLK_PIN].gpio_device, PIN_MAP[BOARD_JTCK_SWCLK_PIN].gpio_bit, - GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(PIN_MAP[BOARD_JTDI_PIN].gpio_device, PIN_MAP[BOARD_JTDI_PIN].gpio_bit, - GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(PIN_MAP[BOARD_JTDO_PIN].gpio_device, PIN_MAP[BOARD_JTDO_PIN].gpio_bit, - GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - gpio_set_modef(PIN_MAP[BOARD_NJTRST_PIN].gpio_device, PIN_MAP[BOARD_NJTRST_PIN].gpio_bit, - GPIO_MODE_AF, GPIO_MODEF_TYPE_PP); - - gpio_set_af(PIN_MAP[BOARD_JTMS_SWDIO_PIN].gpio_device, PIN_MAP[BOARD_JTMS_SWDIO_PIN].gpio_bit, GPIO_AF_0); - gpio_set_af(PIN_MAP[BOARD_JTCK_SWCLK_PIN].gpio_device, PIN_MAP[BOARD_JTCK_SWCLK_PIN].gpio_bit, GPIO_AF_0); - gpio_set_af(PIN_MAP[BOARD_JTDI_PIN].gpio_device, PIN_MAP[BOARD_JTDI_PIN].gpio_bit, GPIO_AF_0); - gpio_set_af(PIN_MAP[BOARD_JTDO_PIN].gpio_device, PIN_MAP[BOARD_JTDO_PIN].gpio_bit, GPIO_AF_0); - gpio_set_af(PIN_MAP[BOARD_NJTRST_PIN].gpio_device, PIN_MAP[BOARD_NJTRST_PIN].gpio_bit, GPIO_AF_0); -} diff --git a/STM32F3/cores/maple/wirish/usb_serial.cpp b/STM32F3/cores/maple/wirish/usb_serial.cpp deleted file mode 100644 index d21766f..0000000 --- a/STM32F3/cores/maple/wirish/usb_serial.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief USB virtual serial terminal - */ - -#include - -#include -#include - -#include -#include -#include - -#include - -/* - * Hooks used for bootloader reset signalling - */ - -#if BOARD_HAVE_SERIALUSB -static void rxHook(unsigned, void*); -static void ifaceSetupHook(unsigned, void*); -#endif - -/* - * USBSerial interface - */ - -#define USB_TIMEOUT 50 - -USBSerial::USBSerial(void) { -#if !BOARD_HAVE_SERIALUSB - ASSERT(0); -#endif -} - -void USBSerial::begin(void) { -#if BOARD_HAVE_SERIALUSB - usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); - usb_cdcacm_set_hooks(USB_CDCACM_HOOK_RX, rxHook); - usb_cdcacm_set_hooks(USB_CDCACM_HOOK_IFACE_SETUP, ifaceSetupHook); -#endif -} - -void USBSerial::end(void) { -#if BOARD_HAVE_SERIALUSB - usb_cdcacm_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); - usb_cdcacm_remove_hooks(USB_CDCACM_HOOK_RX | USB_CDCACM_HOOK_IFACE_SETUP); -#endif -} - -void USBSerial::write(uint8 ch) { - this->write(&ch, 1); -} - -void USBSerial::write(const char *str) { - this->write(str, strlen(str)); -} - -void USBSerial::write(const void *buf, uint32 len) { - if (!this->isConnected() || !buf) { - return; - } - - uint32 txed = 0; - uint32 old_txed = 0; - uint32 start = millis(); - - uint32 sent = 0; - - while (txed < len && (millis() - start < USB_TIMEOUT)) { - sent = usb_cdcacm_tx((const uint8*)buf + txed, len - txed); - txed += sent; - if (old_txed != txed) { - start = millis(); - } - old_txed = txed; - } - - - if (sent == USB_CDCACM_TX_EPSIZE) { - while (usb_cdcacm_is_transmitting() != 0) { - } - /* flush out to avoid having the pc wait for more data */ - usb_cdcacm_tx(NULL, 0); - } -} - -uint32 USBSerial::available(void) { - return usb_cdcacm_data_available(); -} - -uint32 USBSerial::read(void *buf, uint32 len) { - if (!buf) { - return 0; - } - - uint32 rxed = 0; - while (rxed < len) { - rxed += usb_cdcacm_rx((uint8*)buf + rxed, len - rxed); - } - - return rxed; -} - -/* Blocks forever until 1 byte is received */ -uint8 USBSerial::read(void) { - uint8 b; - this->read(&b, 1); - return b; -} - -uint8 USBSerial::pending(void) { - return usb_cdcacm_get_pending(); -} - -uint8 USBSerial::isConnected(void) { - return usb_is_connected(USBLIB) && usb_is_configured(USBLIB); -} - -uint8 USBSerial::getDTR(void) { - return usb_cdcacm_get_dtr(); -} - -uint8 USBSerial::getRTS(void) { - return usb_cdcacm_get_rts(); -} - -#if BOARD_HAVE_SERIALUSB -USBSerial SerialUSB; -#endif - -/* - * Bootloader hook implementations - */ - -#if BOARD_HAVE_SERIALUSB - -enum reset_state_t { - DTR_UNSET, - DTR_HIGH, - DTR_NEGEDGE, - DTR_LOW -}; - -static reset_state_t reset_state = DTR_UNSET; - -static void ifaceSetupHook(unsigned hook, void *requestvp) { - uint8 request = *(uint8*)requestvp; - - // Ignore requests we're not interested in. - if (request != USB_CDCACM_SET_CONTROL_LINE_STATE) { - return; - } - - // We need to see a negative edge on DTR before we start looking - // for the in-band magic reset byte sequence. - uint8 dtr = usb_cdcacm_get_dtr(); - switch (reset_state) { - case DTR_UNSET: - reset_state = dtr ? DTR_HIGH : DTR_LOW; - break; - case DTR_HIGH: - reset_state = dtr ? DTR_HIGH : DTR_NEGEDGE; - break; - case DTR_NEGEDGE: - reset_state = dtr ? DTR_HIGH : DTR_LOW; - break; - case DTR_LOW: - reset_state = dtr ? DTR_HIGH : DTR_LOW; - break; - } -} - -#define RESET_DELAY 100000 -static void wait_reset(void) { - delay_us(RESET_DELAY); - nvic_sys_reset(); -} - -#define STACK_TOP 0x20000800 -#define EXC_RETURN 0xFFFFFFF9 -#define DEFAULT_CPSR 0x61000000 -static void rxHook(unsigned hook, void *ignored) { - /* FIXME this is mad buggy; we need a new reset sequence. E.g. NAK - * after each RX means you can't reset if any bytes are waiting. */ - if (reset_state == DTR_NEGEDGE) { - reset_state = DTR_LOW; - - if (usb_cdcacm_data_available() >= 4) { - // The magic reset sequence is "1EAF". - static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; - uint8 chkBuf[4]; - - // Peek at the waiting bytes, looking for reset sequence, - // bailing on mismatch. - usb_cdcacm_peek(chkBuf, 4); - for (unsigned i = 0; i < sizeof(magic); i++) { - if (chkBuf[i] != magic[i]) { - return; - } - } - - // Got the magic sequence -> reset, presumably into the bootloader. - // Return address is wait_reset, but we must set the thumb bit. - uintptr_t target = (uintptr_t)wait_reset | 0x1; - asm volatile("mov r0, %[stack_top] \n\t" // Reset stack - "mov sp, r0 \n\t" - "mov r0, #1 \n\t" - "mov r1, %[target_addr] \n\t" - "mov r2, %[cpsr] \n\t" - "push {r2} \n\t" // Fake xPSR - "push {r1} \n\t" // PC target addr - "push {r0} \n\t" // Fake LR - "push {r0} \n\t" // Fake R12 - "push {r0} \n\t" // Fake R3 - "push {r0} \n\t" // Fake R2 - "push {r0} \n\t" // Fake R1 - "push {r0} \n\t" // Fake R0 - "mov lr, %[exc_return] \n\t" - "bx lr" - : - : [stack_top] "r" (STACK_TOP), - [target_addr] "r" (target), - [exc_return] "r" (EXC_RETURN), - [cpsr] "r" (DEFAULT_CPSR) - : "r0", "r1", "r2"); - /* Can't happen. */ - ASSERT_FAULT(0); - } - } -} - -#endif // BOARD_HAVE_SERIALUSB diff --git a/STM32F3/cores/maple/wirish/usb_serial.h b/STM32F3/cores/maple/wirish/usb_serial.h deleted file mode 100644 index f36671b..0000000 --- a/STM32F3/cores/maple/wirish/usb_serial.h +++ /dev/null @@ -1,67 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief Wirish USB virtual serial port (SerialUSB). - */ - -#ifndef _WIRISH_USB_SERIAL_H_ -#define _WIRISH_USB_SERIAL_H_ - -#include -#include - -/** - * @brief Virtual serial terminal. - */ -class USBSerial : public Print { -public: - USBSerial(void); - - void begin(void); - void end(void); - - uint32 available(void); - - uint32 read(void *buf, uint32 len); - uint8 read(void); - - void write(uint8); - void write(const char *str); - void write(const void*, uint32); - - uint8 getRTS(); - uint8 getDTR(); - uint8 isConnected(); - uint8 pending(); -}; - -#if BOARD_HAVE_SERIALUSB -extern USBSerial SerialUSB; -#endif - -#endif - diff --git a/STM32F3/cores/maple/wirish/wirish.h b/STM32F3/cores/maple/wirish/wirish.h deleted file mode 100644 index f1884b5..0000000 --- a/STM32F3/cores/maple/wirish/wirish.h +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief Main include file for the Wirish core. - * - * Includes most of Wirish, and (transitively or otherwise) - * substantial pieces of libmaple proper. - */ - -#ifndef _WIRISH_WIRISH_H_ -#define _WIRISH_WIRISH_H_ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if (STM32_MCU_SERIES == STM32_SERIES_F1) || (STM32_MCU_SERIES == STM32_SERIES_F3) /* FIXME [0.0.13?] port to F2 */ -#include -#endif -#include -#include -#include -#include - -#include - -#include - -/* Wiring macros and bit defines */ - -#define true 0x1 -#define false 0x0 - -#define LSBFIRST 0 -#define MSBFIRST 1 - -#define lowByte(w) ((w) & 0xFF) -#define highByte(w) (((w) >> 8) & 0xFF) -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : \ - bitClear(value, bit)) -#define bit(b) (1UL << (b)) - -#endif - diff --git a/STM32F3/cores/maple/wirish/wirish_analog.cpp b/STM32F3/cores/maple/wirish/wirish_analog.cpp deleted file mode 100644 index 91ca0e2..0000000 --- a/STM32F3/cores/maple/wirish/wirish_analog.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/wirish_analog.cpp - * @brief Wiring-style analogRead() implementation. - */ - -#include -#include -#include - -/* Unlike Wiring and Arduino, this assumes that the pin's mode is set - * to INPUT_ANALOG. That's faster, but it does require some extra work - * on the user's part. Not too much, we think ;). */ -uint16 analogRead(uint8 pin) { - const adc_dev *dev = PIN_MAP[pin].adc_device; - if (dev == NULL) { - return 0; - } - - return adc_read(dev, PIN_MAP[pin].adc_channel); -} diff --git a/STM32F3/cores/maple/wirish/wirish_debug.h b/STM32F3/cores/maple/wirish/wirish_debug.h deleted file mode 100644 index 4edfd27..0000000 --- a/STM32F3/cores/maple/wirish/wirish_debug.h +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/wirish_debug.h - * @brief High level debug port configuration - */ - -#ifndef _WIRISH_WIRISH_DEBUG_H_ -#define _WIRISH_WIRISH_DEBUG_H_ - -#include - -/** - * @brief Disable the JTAG and Serial Wire (SW) debug ports. - * - * You can call this function in order to use the JTAG and SW debug - * pins as ordinary GPIOs. - * - * @see enableDebugPorts() - */ -void disableDebugPorts(void); - -/** - * @brief Enable the JTAG and Serial Wire (SW) debug ports. - * - * After you call this function, the JTAG and SW debug pins will no - * longer be usable as GPIOs. - * - * @see disableDebugPorts() - */ -void enableDebugPorts(void); - -#endif diff --git a/STM32F3/cores/maple/wirish/wirish_digital.cpp b/STM32F3/cores/maple/wirish/wirish_digital.cpp deleted file mode 100644 index 2711a33..0000000 --- a/STM32F3/cores/maple/wirish/wirish_digital.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/* - * Arduino-compatible digital I/O implementation. - */ - -#include - -#include -#include - -#include -#include - -uint32 digitalRead(uint8 pin) { - if (pin >= BOARD_NR_GPIO_PINS) { - return 0; - } - - return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ? - HIGH : LOW; -} - -void digitalWrite(uint8 pin, uint8 val) { - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - - gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val); -} - -void togglePin(uint8 pin) { - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - - gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit); -} - -#define BUTTON_DEBOUNCE_DELAY 1 - -uint8 isButtonPressed(uint8 pin, uint32 pressedLevel) { - if (digitalRead(pin) == pressedLevel) { - delay(BUTTON_DEBOUNCE_DELAY); - while (digitalRead(pin) == pressedLevel) - ; - return true; - } - return false; -} - -uint8 waitForButtonPress(uint32 timeout) { - uint32 start = millis(); - uint32 time; - if (timeout == 0) { - while (!isButtonPressed()) - ; - return true; - } - do { - time = millis(); - /* properly handle wrap-around */ - if ((start > time && time + (0xffffffffU - start) > timeout) || - time - start > timeout) { - return false; - } - } while (!isButtonPressed()); - return true; -} diff --git a/STM32F3/cores/maple/wirish/wirish_math.cpp b/STM32F3/cores/maple/wirish/wirish_math.cpp deleted file mode 100644 index 1443b3c..0000000 --- a/STM32F3/cores/maple/wirish/wirish_math.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Modified by LeafLabs, LLC. - * - * Part of the Wiring project - http://wiring.org.co Copyright (c) - * 2004-06 Hernando Barragan Modified 13 August 2006, David A. Mellis - * for Arduino - http://www.arduino.cc/ - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include - -void randomSeed(unsigned int seed) { - if (seed != 0) { - srand(seed); - } -} - -long random(long howbig) { - if (howbig == 0) { - return 0; - } - - return rand() % howbig; -} - -long random(long howsmall, long howbig) { - if (howsmall >= howbig) { - return howsmall; - } - - long diff = howbig - howsmall; - return random(diff) + howsmall; -} - diff --git a/STM32F3/cores/maple/wirish/wirish_math.h b/STM32F3/cores/maple/wirish/wirish_math.h deleted file mode 100644 index 39f16a0..0000000 --- a/STM32F3/cores/maple/wirish/wirish_math.h +++ /dev/null @@ -1,151 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/wirish_math.h - * @brief Includes ; provides Wiring-compatible math routines. - */ - -#ifndef _WIRISH_WIRISH_MATH_H_ -#define _WIRISH_WIRISH_MATH_H_ - -#include - -/** - * @brief Initialize the pseudo-random number generator. - * @param seed the number used to initialize the seed; cannot be zero. - */ -void randomSeed(unsigned int seed); - -/** - * @brief Generate a pseudo-random number with upper bound. - * @param max An upper bound on the returned value, exclusive. - * @return A pseudo-random number in the range [0,max). - * @see randomSeed() - */ -long random(long max); - -/** - * @brief Generate a pseudo-random number with lower and upper bounds. - * @param min Lower bound on the returned value, inclusive. - * @param max Upper bound on the returned value, exclusive. - * @return A pseudo-random number in the range [min, max). - * @see randomSeed() - */ -long random(long min, long max); - -/** - * @brief Remap a number from one range to another. - * - * That is, a value equal to fromStart gets mapped to toStart, a value - * of fromEnd to toEnd, and other values are mapped proportionately. - * - * Does not constrain value to lie within [fromStart, fromEnd]. - * - * If a "start" value is larger than its corresponding "end", the - * ranges are reversed, so map(n, 1, 10, 10, 1) would reverse the - * range [1,10]. - * - * Negative numbers may appear as any argument. - * - * @param value the value to map. - * @param fromStart the beginning of the value's current range. - * @param fromEnd the end of the value's current range. - * @param toStart the beginning of the value's mapped range. - * @param toEnd the end of the value's mapped range. - * @return the mapped value. - */ -static inline long map(long value, long fromStart, long fromEnd, - long toStart, long toEnd) { - return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) + - toStart; -} - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 - -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) -#define radians(deg) ((deg)*DEG_TO_RAD) -#define degrees(rad) ((rad)*RAD_TO_DEG) -#define sq(x) ((x)*(x)) - -/* undefine stdlib's abs if encountered */ -#ifdef abs -#undef abs -#endif -#define abs(x) (((x) > 0) ? (x) : -(x)) - -/* Following are duplicate declarations (with Doxygen comments) for - * some of the math.h functions; this is for the convenience of the - * Sphinx docs. - */ - -/** - * Compute the cosine of an angle, in radians. - * @param x The radian measure of the angle. - * @return The cosine of x. This value will be between -1 and 1. - */ -double cos(double x); - -/** - * Compute the sine of an angle, in radians. - * @param x The radian measure of the angle. - * @return The sine of x. This value will be between -1 and 1. - */ -double sin(double x); - -/** - * Compute the tangent of an angle, in radians. - * @param x The radian measure of the angle. - * @return The tangent of x. There are no limits on the return value - * of this function. - */ -double tan(double x); - -/** - * Compute the square root of a number. - * @param x The number whose square root to find. This value cannot - * be negative. - * @return The square root of x. The return value is never negative. - */ -double sqrt(double x); - -/** - * Compute an exponentiation. - * @param x the base. This value cannot be zero if y <= 0. This value - * cannot be negative if y is not an integral value. - * @param y the exponent. - * @return x raised to the power y. - */ -double pow(double x, double y); - -#endif diff --git a/STM32F3/cores/maple/wirish/wirish_shift.cpp b/STM32F3/cores/maple/wirish/wirish_shift.cpp deleted file mode 100644 index a032d50..0000000 --- a/STM32F3/cores/maple/wirish/wirish_shift.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#include - -void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value) { - digitalWrite(clockPin, LOW); - for (int i = 0; i < 8; i++) { - int bit = bitOrder == LSBFIRST ? i : (7 - i); - digitalWrite(dataPin, (value >> bit) & 0x1); - togglePin(clockPin); - togglePin(clockPin); - } -} diff --git a/STM32F3/cores/maple/wirish/wirish_time.cpp b/STM32F3/cores/maple/wirish/wirish_time.cpp deleted file mode 100644 index 9ce934b..0000000 --- a/STM32F3/cores/maple/wirish/wirish_time.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief Delay implementation. - */ - -#include - -#include -#include - -void delay(unsigned long ms) { - uint32 i; - for (i = 0; i < ms; i++) { - delayMicroseconds(1000); - } -} - -void delayMicroseconds(uint32 us) { - delay_us(us); -} diff --git a/STM32F3/cores/maple/wirish/wirish_time.h b/STM32F3/cores/maple/wirish/wirish_time.h deleted file mode 100644 index eb6c68f..0000000 --- a/STM32F3/cores/maple/wirish/wirish_time.h +++ /dev/null @@ -1,95 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/wirish_time.h - * @brief Timing and delay functions. - */ - -#ifndef _WIRISH_WIRISH_TIME_H_ -#define _WIRISH_WIRISH_TIME_H_ - -#include -#include - -#include - -/** - * Returns time (in milliseconds) since the beginning of program - * execution. On overflow, restarts at 0. - * @see micros() - */ -static inline uint32 millis(void) { - return systick_uptime(); -} - -/** - * Returns time (in microseconds) since the beginning of program - * execution. On overflow, restarts at 0. - * @see millis() - */ -static inline uint32 micros(void) { - uint32 ms; - uint32 cycle_cnt; - - do { - ms = millis(); - cycle_cnt = systick_get_count(); - } while (ms != millis()); - -#define US_PER_MS 1000 - /* SYSTICK_RELOAD_VAL is 1 less than the number of cycles it - * actually takes to complete a SysTick reload */ - return ((ms * US_PER_MS) + - (SYSTICK_RELOAD_VAL + 1 - cycle_cnt) / CYCLES_PER_MICROSECOND); -#undef US_PER_MS -} - -/** - * Delay for at least the given number of milliseconds. - * - * Interrupts, etc. may cause the actual number of milliseconds to - * exceed ms. However, this function will return no less than ms - * milliseconds from the time it is called. - * - * @param ms the number of milliseconds to delay. - * @see delayMicroseconds() - */ -void delay(unsigned long ms); - -/** - * Delay for at least the given number of microseconds. - * - * Interrupts, etc. may cause the actual number of microseconds to - * exceed us. However, this function will return no less than us - * microseconds from the time it is called. - * - * @param us the number of microseconds to delay. - * @see delay() - */ -void delayMicroseconds(uint32 us); - -#endif diff --git a/STM32F3/cores/maple/wirish/wirish_types.h b/STM32F3/cores/maple/wirish/wirish_types.h deleted file mode 100644 index fce895e..0000000 --- a/STM32F3/cores/maple/wirish/wirish_types.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/include/wirish/wirish_types.h - * @author Marti Bolivar - * @brief Wirish library type definitions. - */ - -#ifndef _WIRISH_WIRISH_TYPES_H_ -#define _WIRISH_WIRISH_TYPES_H_ - -#include -#include -#include -#include - -/** - * Invalid stm32_pin_info adc_channel value. - * @see stm32_pin_info - */ -#define ADCx 0xFF - -/** - * @brief Stores STM32-specific information related to a given Maple pin. - * @see PIN_MAP - */ -typedef struct stm32_pin_info { - gpio_dev *gpio_device; /**< Maple pin's GPIO device */ - timer_dev *timer_device; /**< Pin's timer device, if any. */ - const adc_dev *adc_device; /**< ADC device, if any. */ - uint8 gpio_bit; /**< Pin's GPIO port bit. */ - uint8 timer_channel; /**< Timer channel, or 0 if none. */ - uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */ -} stm32_pin_info; - -/** - * Variable attribute, instructs the linker to place the marked - * variable in Flash instead of RAM. */ -#define __FLASH__ __attr_flash - -typedef uint8 boolean; -typedef uint8 byte; - -#endif diff --git a/STM32F3/examples/Blinkf3/Blinkf3.ino b/STM32F3/examples/Blinkf3/Blinkf3.ino deleted file mode 100644 index 2bcb929..0000000 --- a/STM32F3/examples/Blinkf3/Blinkf3.ino +++ /dev/null @@ -1,38 +0,0 @@ -/* - Blink - Turns on an LED on for one second, then off for one second, repeatedly. - - Most Arduinos have an on-board LED you can control. On the Uno and - Leonardo, it is attached to digital pin 13. If you're unsure what - pin the on-board LED is connected to on your Arduino model, check - the documentation at http://arduino.cc - - This example code is in the public domain. - - modified 8 May 2014 - by Scott Fitzgerald - - modified for stm32f3discovery - 2015/02 by Frank-Michael Krause - */ - - -// the setup function runs once when you press reset or power the board -void setup() { - // initialize pins PE8, PE9 as an output. - pinMode(PE8, OUTPUT); - pinMode(PE9, OUTPUT); - Serial2.begin(9600); - Serial2.println("Hello world"); - -} - -// the loop function runs over and over again forever -void loop() { - digitalWrite(PE8, HIGH); // turn the LED on (HIGH is the voltage level) - digitalWrite(PE9, LOW); // turn the LED off by making the voltage LOW - delay(100); // wait for a second - digitalWrite(PE8, LOW); // turn the LED off by making the voltage LOW - digitalWrite(PE9, HIGH); // turn the LED on (HIGH is the voltage level) - delay(300); // wait for a second -} diff --git a/STM32F3/examples/f3_buttondemo/f3_buttondemo.ino b/STM32F3/examples/f3_buttondemo/f3_buttondemo.ino deleted file mode 100644 index c6a9c0d..0000000 --- a/STM32F3/examples/f3_buttondemo/f3_buttondemo.ino +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - - -/* - * This demo shows how to handle the blue button of the stm32f3discovery board - * - * Dieses Beispiel zeigt, wie die blaue Taste des Boards abgefragt werden kann. - * Es wird eine LED ein- bzw. ausgeschaltet. - */ - - -void setup() // Init-Funktion -{ - // BOARD_LED_PIN ist PE10 - pinMode(BOARD_LED_PIN, OUTPUT); - - // BOARD_BUTTTON_PIN ist PA0 - pinMode(BOARD_BUTTON_PIN, INPUT); - -} - - -void loop() -{ - if (isButtonPressed()) - togglePin(BOARD_LED_PIN); -} - - - diff --git a/STM32F3/examples/f3_functionTimer/f3_functionTimer.ino b/STM32F3/examples/f3_functionTimer/f3_functionTimer.ino deleted file mode 100644 index ca8fce9..0000000 --- a/STM32F3/examples/f3_functionTimer/f3_functionTimer.ino +++ /dev/null @@ -1,144 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - - -#include -#include - -/* - * Demo program function timer - * - * You can define functions register those functions at the timer system - * to be called after the time in ms given at timer start - * - * - there are 10 timers with id from 0 to 9 - * - the id has to be given at timer start - * - there can only be running one instance of a timer id at one time - * - at each timer start another function can be registered - * - time resolution is 5ms - * - * The registered function will be executed in interrupt context. - * Therefore the timer funtion shall be execute very fast. - * - * If using functtion timer and ultrasonic sensors in parallel the measurement results of - * the sensors can be slightly wrong. - * - * This demo controls three LEDs with different blinking rythms - */ - - -/* - * Demoprogramm fuer Funktions-Timer - * - * Es koennen Funktionen definiert und dem Timersystem-uebergeben werden, - * die nach einer uebergebenen Zeit aufgerufen werden. - * - * - Jeder Timer hat eine id zwischen 0 und 9, die beim Start angegeben werden muss. - * - Es kann nur ein Timer pro Id zu gleichen Zeit laufen - * - Es kann bei jedem Start eines Timers eine andere Funktion uebergeben werden. - * - * Die uebergebene Funktion wird im Interrupt-Kontext ausgefuehrt und unterbricht das - * normal in setup/loop ausgefuehrte Programm an beliebiger Stelle. - * Es ist darauf zu achten, dass die Timerfuntion moeglichst kurz, d.h. schnell ausfuehrbar, ist. - * - * Die parallele Ausfuehrung von Funktionstimern kann die Messergebnisse von Ultraschallsensoren - * leicht verfaelschen! - * - * Das Demoprogramm steuert drei LEDs mit unterschiedlichen Blink-Zeiten an. - * - */ - - - -// 500ms Bink mit Steuerung ueber Timer-Id 0 -#define LED PE9 -int LEDState = 0; -void TimerFunction(int arg) -{ - if (LEDState) - LEDState = 0; - else - LEDState = 1; - digitalWrite(LED, LEDState); - timerStart(0, 500, TimerFunction, 0 ); // restart Timer -} - - -// 900ms Bink mit Steuerung ueber Timer-Id 1 -#define LED1 PE10 -int LED1State = 0; -void Timer1Function(int arg) -{ - if (LED1State) - LED1State = 0; - else - LED1State = 1; - digitalWrite(LED1, LED1State); - timerStart(1, 900, Timer1Function, 0 ); // restart Timer -} - - -// 1300ms Bink mit Steuerung ueber Timer-Id 2 -#define LED2 PE11 -int LED2State = 0; -void Timer2Function(int arg) -{ - if (LED2State) - LED2State = 0; - else - LED2State = 1; - digitalWrite(LED2, LED2State); - timerStart(2, 1300, Timer2Function, 0 ); // restart Timer -} - - - - -void setup() -{ - pinMode(LED, OUTPUT); - pinMode(LED1, OUTPUT); - pinMode(LED2, OUTPUT); - - // Timer-System initialisieren - timerInit(); - - // Timer starten - timerStart(0, 500, TimerFunction, 0 ); - timerStart(1, 900, Timer1Function, 0 ); - timerStart(2, 1300, Timer2Function, 0 ); -} - -void loop() -{ - // Die Programmabarbeitung erfolgt komplett im Interrupt, - // daher muss in loop nichts getan werden - while (1) - ; -} - - - diff --git a/STM32F3/examples/f3_gyrodemo/f3_gyrodemo.ino b/STM32F3/examples/f3_gyrodemo/f3_gyrodemo.ino deleted file mode 100644 index 8e3ca2b..0000000 --- a/STM32F3/examples/f3_gyrodemo/f3_gyrodemo.ino +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include - -#include -#include - - - -/** - * Dieses Beispiel benutzt die Z-Achse des Gyro-Sensors, um eine Drehung des Boards - * zu messen und anzuzeigen. - * Wenn das Board um seine Z-Achse gedreht wird, so zeigt die jeweils aktive LED - * immer in die gleiche Richtung. - * Mit der Zeit ändert sich die angezeigte Richtung, da die Messwerte kleine - * Fehler haben, die sich mit der Zeit aufsummieren und das Programm keine - * Kalibrierung und Fehlerkorrektur enthält. Die Größe des Fehlers ist von - * Board zu Board unterschiedlich. - * - */ - -// Array mit den LED-Pins -int leds[] = { PE9, PE10, PE11, PE12, PE13, PE14, PE15, PE8 }; - - -void setup() // Init-Funktion -{ - // Die 8 LED-Pins auf Ausgang setzen - pinMode (leds[0], OUTPUT); - pinMode (leds[1], OUTPUT); - pinMode (leds[2], OUTPUT); - pinMode (leds[3], OUTPUT); - pinMode (leds[4], OUTPUT); - pinMode (leds[5], OUTPUT); - pinMode (leds[6], OUTPUT); - pinMode (leds[7], OUTPUT); - - // SPI1-Interface initialisieren - gyroSpiInit(); - - // den Gyrochip initialisieren - gyroInit(); - - // Gyro aktivieren - gyroStart(); -} - - -int led_idx; - -void loop() -{ - // Auslesen der Gyro-Messwerte und Berechnen des aktuellen Drehwinkels - gyroUpdate(); - - // Wenn der Winkel 360° überschreitet oder 0° unterschreitet - // werden 360° abgezogen bzw. addiert - if (winkelz>360) - winkelz -= 360; - else if (winkelz<0) - winkelz += 360; - - // aktuell aktive LED abschalten - digitalWrite(leds[led_idx], LOW); - - // anhand des Winkels die neue Aktive LED bestimmen. - // Dazu wird mit Dreisatz der Winkel (0..360) auf die LED (0..7) abgebildet - led_idx = (winkelz*8)/360; - - // aktive LED anschalten - digitalWrite(leds[led_idx], HIGH); - - delay(50); -} - - - diff --git a/STM32F3/examples/f3_lsm303demo/f3_lsm303demo.ino b/STM32F3/examples/f3_lsm303demo/f3_lsm303demo.ino deleted file mode 100644 index 63251aa..0000000 --- a/STM32F3/examples/f3_lsm303demo/f3_lsm303demo.ino +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include -#include -#include - -#include -#include - - -/** - * Dieses Beispiel wertet die x und y Werte des Beschleunigungssensors aus - * und zeigt über die 8 LEDs an, in welche Richtung das Board gekippt wurde. - * Die z-Komponente wird nicht ausgewertet. - */ - - -// Array mit den LED-Pins -int leds[] = { PE9, PE10, PE11, PE12, PE13, PE14, PE15, PE8 }; - - -void setup() // Init-Funktion -{ - // Die 8 LED-Pins auf Ausgang setzen - pinMode (leds[0], OUTPUT); - pinMode (leds[1], OUTPUT); - pinMode (leds[2], OUTPUT); - pinMode (leds[3], OUTPUT); - pinMode (leds[4], OUTPUT); - pinMode (leds[5], OUTPUT); - pinMode (leds[6], OUTPUT); - pinMode (leds[7], OUTPUT); - - // I2C-Interface initialisieren, mit dem der - // Beschleunigungssensor verbunden ist - i2c_master_enable(I2C1, 0); - - // Beschleunigungssensor initialisieren - lsm303Init(); - -} - -// Speicher für die aktuell aktive LED -int led_idx; - -void loop() -{ - float winkel; - - // Beschleunigungssensor lesen - readAccValues(); - - // Winkel entsprechend der gemessenen x und y Komponente - // berechnen - // atan2 gibt den Winkel im Bogenmass zurueck, 2*Pi entsprechen 360° - winkel = atan2(accy*-1.0,accx*1.0); - - // Umrechnung des Winkels auf die 8 LEDs, aus denen der Vollkreis (2*Pi) - // besteht (Dreisatz, Umrechnung mit 4 und Pi) - winkel = (winkel*4)/3.14; - - // Falls der Winkel negativ ist, eine Vollkreis-Wert hinzurechnen - // für unser Beispiel 8 - if (winkel<0) - winkel += 8; - - // alte aktive LED ausschalten - digitalWrite(leds[led_idx], LOW); - - // der Ganzzahl-Anteil des Winkels ist der Index der neuen LED - // Das (int) vor winkel führt die Umwandlung der Kommanzahl in einen Integer-Wert - // durch. Das nennt man einen Type-Cast. Der ist hier nötig, da eine - // float Variable nicht direkt einer Integervariable zugewiesen werden kann - led_idx = (int)winkel; - - // nochmal prüfen, ob der neue Led-Index nicht zu groß ist - // wenn ja auf maximalwert setzen - if (led_idx>7) - led_idx=7; - - // neue LED anschalten - digitalWrite(leds[led_idx], HIGH); - - delay(50); -} - - - diff --git a/STM32F3/examples/f3_ultrasonic/f3_ultrasonic.ino b/STM32F3/examples/f3_ultrasonic/f3_ultrasonic.ino deleted file mode 100644 index aa8bc5c..0000000 --- a/STM32F3/examples/f3_ultrasonic/f3_ultrasonic.ino +++ /dev/null @@ -1,137 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#include -#include -#include - -/* - * Demoprogramm für den Betrieb von Ultraschallsensoren über Interrupts. - * - * Diese Betriebsart hat den Vorteil, dass während der Messung (die einige 10ms dauern kann) - * andere Dinge erledigt werden können. - * - * Es kann ständig im Hintergrund gemessen werden und der letzte gültige oder der aktuelle - * Messwert per Funktion abgefragt werden. - * - * Außerdem kann eine Callbackfunktion pro Sensor registriert werden, die nach einer erfolgten - * Messung aufgerufen wird. ZU beachten ist, dass diese Funktion im Interrupt-Kontext aufgerufen wird - * und daher möglichst kurz (d.h. schnell abarbeitbar) sein. - * Bei Debug-Ausgaben in der Handler-Funktion können sich die Ausgaben in Ausgaben aus loop() heraus "hineindrängeln" - * - */ - - -//----------------- Ultraschall ----------------------- -// 3x HC-SR04 - -#define US1_ECHO PD4 -#define US1_TRIGGER PB4 - -#define US2_ECHO PD5 -#define US2_TRIGGER PB5 - -#define US3_ECHO PD6 -#define US3_TRIGGER PB8 - - - -void UsHandler(int id, int entfernung) -{ - Print2Number("Sensor", id, entfernung); -} - - -void setup() -{ - delay(150); - debugInit(); - debugSetTimeStamp(DDEBUG_TIME_STAMP_ON); - - // Ultraschallsensoren definieren - addUSSensor(0, US1_TRIGGER, US1_ECHO, 220); - addUSSensor(1, US2_TRIGGER, US2_ECHO, 220); - addUSSensor(2, US3_TRIGGER, US3_ECHO); - - UsAttachHandler(0, UsHandler); - UsSetMessPause(100); // Pause von 100 ms nach jeder Messung - // damit die Ausgabe im Terminal nicht zu schnell wird - // Im Normalfall würde keine so lange Pause programmiert werden. - // Die Pause ist nur nötig, wenn festgestellt wird, dass sich - // die Sensoren gegenseitig durch nachfolgende mehrfache Echos beeinflussen. - // Das ist Umgebungsabhängig. - - debugPrint("activate Sensor 0 ---------------"); - aktiviereUSSensor(0); - PrintUsSensorList(); - debugPrint("activate Sensor 1 ---------------"); - aktiviereUSSensor(1); - PrintUsSensorList(); - - debugPrint("activate Sensor 2 ---------------"); - aktiviereUSSensor(2); - PrintUsSensorList(); - - // ab jetzt wird im Hintergrund gemessen - - delay(1000); - debugPrint("deactivate Sensor 2 ---------------"); - deaktiviereUSSensor(2); - PrintUsSensorList(); - - delay(1000); - debugPrint("deactivate Sensor 1 ---------------"); - deaktiviereUSSensor(1); - PrintUsSensorList(); - - delay(1000); - debugPrint("deactivate Sensor 0 ---------------"); - deaktiviereUSSensor(0); - PrintUsSensorList(); - - delay(1000); - debugPrint("activate Sensor 0 ---------------"); - aktiviereUSSensor(0); - PrintUsSensorList(); - - delay(1000); - debugPrint("activate Sensor 1 ---------------"); - aktiviereUSSensor(1); - PrintUsSensorList(); - - - debugPrint("Programm gestartet"); -} - -void loop() -{ - Print2Number("Sensor 1", UsLetzterGueltigerMesswert(1), UsLetzterGueltigerMesswertAlter(1)); - delay(300); -} - - - - diff --git a/STM32F3/libraries/gyro/gyro.cpp b/STM32F3/libraries/gyro/gyro.cpp deleted file mode 100644 index ef3722c..0000000 --- a/STM32F3/libraries/gyro/gyro.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @brief functions for accessing l3g20 gyro on stm32f3discovery board - * - * SPI1 is set up to be a master - * at 9 MHz (SPI_1_125MHZ), - * 8 Bit - * MSB first in/out (MSBFIRST) - * MODE 0 // following the datasheet it should be MODE 3 but 0 is working too - * - * Pin PE3 is used as slave select, as defined for SPI1 in board.h - * - * There is no interrupt support because I was not able to get out any int2-output of the chip - * - */ - -#include -#include "l3gd20.h" -#include "../ringbuffer/ringbuffer.h" -#include "gyro.h" - - -#define NSS PE3 -#define GYRO_FIFO_WATERMARK 10 - -HardwareSPI spi1(1); -static uint8 gyroValuesSingle[6]; - -static int GYRO_BIAS_X = -75; -static int GYRO_BIAS_Y = 94; -static int GYRO_BIAS_Z = 0; - -float winkelx, winkely, winkelz; -int gyroxRaw, gyroyRaw, gyrozRaw; // bei jedem Update wird ein Datensatz der gelesenen - // Werte in den Raw-Variablen gespeichert um den Bias prüfen zu - // können - -#define RB_SIZE 256 -#define GYRO_AVERAGE_X 120 -#define GYRO_AVERAGE_Y 120 -#define GYRO_AVERAGE_Z 120 - -static int rbvx[RB_SIZE]; -static int rbvy[RB_SIZE]; -static int rbvz[RB_SIZE]; -static RingBufferAverage rbx(RB_SIZE, rbvx, NULL, GYRO_AVERAGE_X); -static RingBufferAverage rby(RB_SIZE, rbvy, NULL, GYRO_AVERAGE_Y); -static RingBufferAverage rbz(RB_SIZE, rbvz, NULL, GYRO_AVERAGE_Z); - -static int averageActiveX = 0; -static int averageActiveY = 0; -static int averageActiveZ = 0; - -void readGyroValues() -{ - int j; - digitalWrite(NSS, LOW); - spi1.transfer(0xA8|0x40); - - for (j=0; j<6; j++) - gyroValuesSingle[j] = spi1.transfer(0); - - digitalWrite(NSS, HIGH); -} - -uint8 gyroReadRegister(uint8 reg) -{ - digitalWrite(NSS, LOW); - spi1.transfer(reg|0x80); - - uint8 val = spi1.transfer(0); - - digitalWrite(NSS, HIGH); - return val; -} - -void gyroWriteRegister(uint8 reg, uint8 val) -{ - digitalWrite(NSS, LOW); - spi1.transfer(reg); - spi1.transfer(val); - digitalWrite(NSS, HIGH); -} - -/** - * Initialisiert das spi1 interface des stm32f3discovery - */ -void gyroSpiInit() -{ - spi1.begin(SPI_9MHZ, MSBFIRST, 0); - /* NSS is usually active LOW, so initialize it HIGH */ - pinMode(NSS, OUTPUT); - digitalWrite(NSS, HIGH); -} - -#define GYRO_OP_PARAMS (GYRO_ODR_190|GYRO_LP_BW1|GYRO_ENABLE) - -/** - * konfiguriert den Gyro. - * der Gyro ist nach dem Aufruf der Funktion aktiv. Wird er nicht mehr benötigt, kann er - * mir gyroStop() wieder deaktiviert werden. Für eine Reaktivierung kann die Funktion - * gyroStart() verwendet werden. - * - * Im aktiven Zustand muss im Abstand von höchstens 120ms die Funktion gyroUpdate() - * aufgerufen werden. - * - * Die globalen Variablen winkelx, winkely und winkelz enthalten den jeweils aktuellen winkel. - * Die Funktion gyroResetWinkel setzt die globalen Variablen wieder auf 0. - */ -void gyroInit() -{ - /* Initialize SPI */ - // gyroSpiInit(); --> called aus dem Anwendungsmodul, - // da an SPI1 noch weitere Geräte betrieben werden - - // Initialize GyroChip - // 190Hz data Rate, 50Hz Bandwidth - gyroWriteRegister(GYRO_REG_CTRL_REG1, GYRO_OP_PARAMS); - - // CTRL_REG2 --> no High Pass --> nothing to change - - // enable Watermark interrupt on INT2 --> not working no int pulse - // gyroWriteRegister(GYRO_REG_CTRL_REG3, GYRO_I2_EN|GYRO_I2_WTM); - - // set resolution to 500 dps - gyroWriteRegister(GYRO_REG_CTRL_REG4, GYRO_FULL_SCALE_500); - - // enable FIFO, Output after second LP-Filter, no HP - gyroWriteRegister(GYRO_REG_CTRL_REG5, GYRO_FIFO_ENABLE|GYRO_OUT_SELECT2); - //gyroWriteRegister(GYRO_REG_CTRL_REG5, GYRO_OUT_SELECT2); - - //Fifomode and watermark - gyroWriteRegister(GYRO_REG_FIFO_CTRL, GYRO_FIFO_MODE_STREAM|GYRO_FIFO_WATERMARK); -} - -/** - * Es werden 1000 Werte eingelesen (ca. 5,5s) und aus den Werten die Drift-Kompensations- - * werte gemittelt. Der Gyro darf während der Zeit nicht bewegt werden. - */ -void gyroCalibrate() { - int count = 0; - int sumx=0,sumy=0,sumz=0; - - #ifdef DEBUG_GYRO - SerialUSB.print("Biaswerte ermitteln "); - #endif - while (count < 1000) - { - delay(100); - uint8 anz = gyroReadRegister(GYRO_REG_FIFO_SRC) & 0x1F; - for (int i=0; i -#include -#include "lsm303reg.h" -#include "../ringbuffer/ringbuffer.h" -#include "lsm303.h" - -#define ACC_FIFO_WATERMARK 10 - -static int ACC_BIAS_X; -static int ACC_BIAS_Y; -static int ACC_BIAS_Z; - - -int accx, accy, accz; - -#define RB_SIZE 64 -#define ACC_AVERAGE_X 60 -#define ACC_AVERAGE_Y 60 -#define ACC_AVERAGE_Z 60 - -static int rbvx[RB_SIZE]; -static long unsigned int rbtx[RB_SIZE]; -static int rbvy[RB_SIZE]; -static long unsigned int rbty[RB_SIZE]; -static int rbvz[RB_SIZE]; -static long unsigned int rbtz[RB_SIZE]; -static RingBuffer rbx(RB_SIZE, rbvx, rbtx); -static RingBuffer rby(RB_SIZE, rbvy, rbty); -static RingBuffer rbz(RB_SIZE, rbvz, rbtz); - -//static int averageActiveX = 0; -//static int averageActiveY = 0; -//static int averageActiveZ = 0; - - -static uint8 write_msg_data[3]; -static i2c_msg write_msg; - -static uint8 read_msg_data[7]; -static i2c_msg read_msg; - - -void readAccValues() -{ - int16 *p; - write_msg_data[0] = LSM303_REG_OUT_X_L_A|LSM303_READ_MULTI_BYTES; // 0x80 -> AutoIncrement address on read - write_msg.length = 1; - i2c_master_xfer(I2C1, &write_msg, 1, 0); - - read_msg.length = 6; - i2c_master_xfer(I2C1, &read_msg, 1, 2); - - p = (int16*)read_msg_data; - accx = *p++ - ACC_BIAS_X; - accy = *p++ - ACC_BIAS_Y; - accz = *p++ - ACC_BIAS_Z; -} - -uint8 accReadRegister(uint8 reg) -{ - write_msg_data[0] = reg; - write_msg.length = 1; - i2c_master_xfer(I2C1, &write_msg, 1, 0); - - read_msg.length = 1; - i2c_master_xfer(I2C1, &read_msg, 1, 2); - - return read_msg_data[0]; -} - -void accWriteRegister(uint8 reg, uint8 val) -{ - write_msg_data[0] = reg; - write_msg_data[1] = val; - write_msg.length = 2; - i2c_master_xfer(I2C1, &write_msg, 1, 0); -} - - -void lsm303I2CInit() -{ - //i2c_master_enable(I2C1, 0); - // Aktivierung des I2C-Busses muss im Hauptprogramm erfolgen, - // da mehrere Komponenten das I2C-Interface benutzen können - // und eine mehrfache Initialisierung nicht funktioniert - - write_msg.addr = LSM303_ADDR_A; - write_msg.flags = 0; // write, 7 bit address - write_msg.length = sizeof(write_msg_data); - write_msg.xferred = 0; - write_msg.data = write_msg_data; - - read_msg.addr = LSM303_ADDR_A; - read_msg.flags = I2C_MSG_READ; - read_msg.length = sizeof(read_msg_data); - read_msg.xferred = 0; - read_msg.data = read_msg_data; - -} - -/** - * Initialisiert und aktiviert den Beschleunigungssensor - * Aktivierung des I2C-Busses muss im Hauptprogramm erfolgen, - * da mehrere Komponenten das I2C-Interface benutzen können - * und eine mehrfache Initialisierung nicht funktioniert - */ -void lsm303Init() -{ - /* Initialize I2C Transfer-Strukturen für den lsm303*/ - lsm303I2CInit(); - - // Initialize ACC-Chip - // 50Hz data Rate - accWriteRegister(LSM303_REG_CTRL_REG1_A, LSM303_A_ODR_50HZ|LSM303_A_ALL_AXIS_EN); - - // CTRL_REG2 --> no High Pass --> nothing to change - - // enable Watermark interrupt on INT2 --> not working no int pulse - // gyroWriteRegister(GYRO_REG_CTRL_REG3, GYRO_I2_EN|GYRO_I2_WTM); - - // sensitivity 2G is default - - // enable FIFO ? - - //Fifomode and watermark -} - - -void accCalibrate() { - int count = 0; - int sumx=0,sumy=0,sumz=0; - - #ifdef DEBUG_ACC - SerialUSB.print("Biaswerte ermitteln "); - #endif - while (count < 100) - { - delay(3); - readAccValues(); - sumx += accx; - sumy += accy; - sumz += accz; - #ifdef DEBUG_ACC - SerialUSB.print("*"); - #endif - count += 1; - } - ACC_BIAS_X = sumx/count; - ACC_BIAS_Y = sumy/count; - ACC_BIAS_Z = sumz/count; - - #ifdef DEBUG_ACC - SerialUSB.println(""); - SerialUSB.print("ACC-BIAS "); - SerialUSB.print(ACC_BIAS_X); SerialUSB.print(" "); - SerialUSB.print(ACC_BIAS_Y); SerialUSB.print(" "); - SerialUSB.println(ACC_BIAS_Z); - #endif -} - - - -void accUpdate() -{ - //uint8 gyroFifoStatus = gyroReadRegister(GYRO_REG_FIFO_SRC); - //uint8 anz = gyroFifoStatus & 0x1F; - - #ifdef DEBUG_ACC -// SerialUSB.print("fifo anz = "); -// SerialUSB.print(anz); -// SerialUSB.print(" "); - #endif - - readAccValues(); - - rbx.addValue(accx); - rby.addValue(accy); - rbz.addValue(accz); - - #ifdef DEBUG_ACC - SerialUSB.print(accx); SerialUSB.print(" "); - SerialUSB.print(accy); SerialUSB.print(" "); - SerialUSB.print(accz); SerialUSB.print(" "); - SerialUSB.println(""); - #endif -} - -void accStart() -{ - rbx.reset(); - rby.reset(); - rbz.reset(); -} - -void accStop() -{ -} - diff --git a/STM32F3/libraries/lsm303/lsm303.h b/STM32F3/libraries/lsm303/lsm303.h deleted file mode 100644 index 78a9d16..0000000 --- a/STM32F3/libraries/lsm303/lsm303.h +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#ifndef LSM303_H -#define LSM303_H - - -#define ACC_AXIS_X 1 -#define ACC_AXIS_Y 2 -#define ACC_AXIS_Z 3 - - -/** - * Initialisiert das spi1 interface des stm32f3discovery und konfiguriert den Gyro. - * der Gyro ist nach dem Aufruf der Funktion aktiv. Wird er nicht mehr benötigt, kann er - * mir gyroStop() wieder deaktiviert werden. Für eine Reaktivierung kann die Funktion - * gyroStart() verwendet werden. - * - * Im aktiven Zustand muss im Abstand von höchstens 120ms die Funktion gyroUpdate() - * aufgerufen werden. - * - * Die globalen Variablen winkelx, winkely und winkelz enthalten den jeweils aktuellen winkel. - * Die Funktion gyroResetWinkel setzt die globalen Variablen wieder auf 0. - */ -extern void lsm303Init(); - - -/** - */ -extern void lsm303Calibrate(); - - -/** - */ -extern void accUpdate(); - -/** - */ -extern void accStart(); - -/** - * Versetzt den Beschleunigungssensor in den Power Down mode - */ -extern void accStop(); - - -//---------------------------------------------------------------------------------- -// gobale Variablen - -extern int accx, accy, accz; - - -extern void readAccValues(); - -#endif diff --git a/STM32F3/libraries/lsm303/lsm303reg.h b/STM32F3/libraries/lsm303/lsm303reg.h deleted file mode 100644 index 7bf3f80..0000000 --- a/STM32F3/libraries/lsm303/lsm303reg.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef __LSM303REG_H_ -#define __LSM303REG_H_ - -#define LSM303_ADDR_A (0x32>>1) -#define LSM303_ADDR_M (0x3C>>1) - -#define LSM303_REG_CTRL_REG1_A 0x20 -#define LSM303_REG_CTRL_REG2_A 0x21 -#define LSM303_REG_CTRL_REG3_A 0x22 -#define LSM303_REG_CTRL_REG4_A 0x23 -#define LSM303_REG_CTRL_REG5_A 0x24 -#define LSM303_REG_CTRL_REG6_A 0x25 -#define LSM303_REG_REFERENCE_A 0x26 -#define LSM303_REG_STATUS_A 0x27 -#define LSM303_REG_OUT_X_L_A 0x28 -#define LSM303_REG_OUT_X_H_A 0x29 -#define LSM303_REG_OUT_Y_L_A 0x2A -#define LSM303_REG_OUT_Y_H_A 0x2B -#define LSM303_REG_OUT_Z_L_A 0x2C -#define LSM303_REG_OUT_Z_H_A 0x2D -#define LSM303_REG_FIFO_CTRL_A 0x2E -#define LSM303_REG_FIFO_SRC_A 0x2F -#define LSM303_REG_INT1_CFG_A 0x30 -#define LSM303_REG_INT1_SRC_A 0x31 -#define LSM303_REG_INT1_THS_A 0x32 -#define LSM303_REG_INT1_DUARATION_A 0x33 -#define LSM303_REG_INT2_CFG_A 0x34 -#define LSM303_REG_INT2_SRC_A 0x35 -#define LSM303_REG_INT2_THS_A 0x36 -#define LSM303_REG_INT2_DURATION_A 0x37 -#define LSM303_REG_CLICK_CFG_A 0x38 -#define LSM303_REG_CLICK_SRC_A 0x39 -#define LSM303_REG_CLICK_THS_A 0x3A -#define LSM303_REG_TIME_LIMIT_A 0x3B -#define LSM303_REG_TIME_LATENCY_A 0x3C -#define LSM303_REG_TIME_WINDOW_A 0x3D - -#define LSM303_READ_MULTI_BYTES 0x80 - - -//================================================================== -// CTRL_REG1 - -#define LSM303_A_ODR_1HZ 0x10 -#define LSM303_A_ODR_10HZ 0x20 -#define LSM303_A_ODR_25HZ 0x30 -#define LSM303_A_ODR_50HZ 0x40 -#define LSM303_A_ODR_100HZ 0x50 -#define LSM303_A_ODR_200HZ 0x60 -#define LSM303_A_ODR_400HZ 0x70 -#define LSM303_A_ODR_1620HZ 0x80 -#define LSM303_A_ODR_1344Hz 0x90 - -#define LSM303_A_LOWPOWER_EN 0x08 -#define LSM303_A_X_EN 0x01 -#define LSM303_A_Y_EN 0x02 -#define LSM303_A_Z_EN 0x04 -#define LSM303_A_ALL_AXIS_EN 0x07 - - -//================================================================== -// CTRL_REG2 - HP-Filter config - -//================================================================== -// CTRL_REG3 - Int1 config - -#define LSM303_A_I1_CLICK 0x80 -#define LSM303_A_I1_AOI1 0x40 -#define LSM303_A_I1_AOI2 0x20 -#define LSM303_A_I1_DRDY1 0x10 -#define LSM303_A_I1_DRDY2 0x08 -#define LSM303_A_I1_WTM 0x04 -#define LSM303_A_I1_OVERRUN 0x02 - - -//================================================================== -// CTRL_REG4 - Sensitivity, Endianess and SPI config - -#define LSM303_A_FS_2G 0x00 // default -#define LSM303_A_FS_4G 0x10 -#define LSM303_A_FS_8G 0x20 -#define LSM303_A_FS_16G 0x30 - - - -//================================================================== -// CTRL_REG5 - Fifo and other - -#define LSM303_A_FIFO_EN 0x40 - -//================================================================== -// CTRL_REG6 - INT2 config - -//================================================================== -// FIFO_CTRL - -#define LSM303_A_FIFO_MODE_BYPASS 0b00000000 -#define LSM303_A_FIFO_MODE_FIFO 0b01000000 -#define LSM303_A_FIFO_MODE_STREAM 0b10000000 -#define LSM303_A_FIFO_MODE_TRIGGER 0b11000000 - -#define LSM303_A_FIFO_TR 0b00100000 - - -//================================================================== -//================================================================== -//================================================================== -// Magnetometer register -//================================================================== -//================================================================== -//================================================================== - -#define LSM303_REG_CRA_M 0x00 -#define LSM303_REG_CRB_M 0x01 -#define LSM303_REG_MR_M 0x02 -#define LSM303_REG_OUTX_H_M 0x03 -#define LSM303_REG_OUTX_L_M 0x04 -#define LSM303_REG_OUTY_H_M 0x05 -#define LSM303_REG_OUTY_L_M 0x06 -#define LSM303_REG_OUTZ_H_M 0x07 -#define LSM303_REG_OUTZ_L_M 0x08 -#define LSM303_REG_Mg_M 0x09 -#define LSM303_REG_IRA_M 0x0A -#define LSM303_REG_IRB_M 0x0B -#define LSM303_REG_IRC_M 0x0C -#define LSM303_REG_TEMP_H_M 0x31 -#define LSM303_REG_TEMP_L_M 0x32 - - -#endif - diff --git a/STM32F3/libraries/ringbuffer/ringbuffer.cpp b/STM32F3/libraries/ringbuffer/ringbuffer.cpp deleted file mode 100644 index 852b2de..0000000 --- a/STM32F3/libraries/ringbuffer/ringbuffer.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include "ringbuffer.h" - -#ifdef WIN32 - -int tmcnt=10; - -unsigned long millis() { return tmcnt++; } -#define NULL 0 - -#else -#include -#endif - - -RingBuffer::RingBuffer(int _size, int *_values, unsigned long *_timeStamps) -{ - size = _size; // muss ZweierPotenz sein - values = _values; // Pointer auf Speicher für Werte - timeStamps = _timeStamps; // optional Pointer auf Speicher für ms timestamps - mask = 0; - int t = size/2; - while (t) - { - mask = (mask<<1)|1; - t = t/2; - } - reset(); -} - - -void RingBuffer::addValue(int value) -{ - values[wrIdx] = value; - - if (timeStamps != NULL) - timeStamps[wrIdx] = millis(); - - if (anz < size) - anz++; - - wrIdx++; - wrIdx &= mask; -} - - -void RingBuffer::reset() -{ - anz = 0; - wrIdx = 0; - rdIdx = 0; - - for (int i=0; i anz) - return 0; - - rdIdx = (wrIdx - distance) & mask; - - lastRead = 0; - - return 1; -} - - -/* - * Setzt rdIdx auf den ersten Wert, für den der zugehörige timeStamp mindestens zurückliegt, - * Es wird das Alter des betreffenden Wertes in ms zurückgegeben - * = wird zurückgegeben, wenn kein Wert mindestens so alt wie gefordert ist oder keine timestamps vorhanden sind - */ -int RingBuffer::setReadIdxDt(int ms) -{ - if (timeStamps == NULL) // keine timeStamps vorhanden - return 0; - - unsigned long aktTime = millis(); - unsigned long dt=0; - int count = 0; - rdIdx = (wrIdx - 1)&mask; // auf letzten eingetragenen Wert setzen - - lastRead = 0; - - while (count ms) - return dt; - count++; - - rdIdx = (rdIdx-1)&mask; - } - - return 0; -} - - -/* - * gibt Wert für rdIdx zurück und incrementiert rdIdx, solange rdIdx < (wrIdx-1) - * ACHTUNG: wird wrPtr erreicht, so wird immer wieder der letzte Wert zurückgegeben! - */ -int RingBuffer::getValue() -{ - int ret = values[rdIdx]; - - if (((rdIdx+1)&mask) == wrIdx) - lastRead = 1; - else - rdIdx = (rdIdx+1)&mask; - - return ret; -} - -/* - * gibt Wert für rdIdx zurück, trägt den zugehörigen timestamp - * in time ein und incrementiert rdIdx, solange rdIdx < wrIdx - * ACHTUNG: wird wrPtr erreicht, so wird immer wieder der letzte Wert zurückgegeben! - */ -int RingBuffer::getValue(unsigned long *time) -{ - int ret = values[rdIdx]; - if ((time != NULL) && (timeStamps!=NULL)) - *time = timeStamps[rdIdx]; - - if (((rdIdx+1)&mask) == wrIdx) - lastRead = 1; - else - rdIdx = (rdIdx+1)&mask; - - return ret; -} - - -/* - * gibt den Wert von rdIdx-1 zurück und decrementiert rdIdx wenn rdIdx-1 != wrIdx - * - */ -int RingBuffer::getPreviousValue() -{ - int idx = (rdIdx-1)&mask; - int ret = values[idx]; - if (idx != wrIdx) // rdIdx darf nicht kleiner als wrIdx werden - rdIdx = idx; - else - lastRead = 1; - return ret; -} - - -/* -`* decrementiert rdPtr und gibt den zugehörigen Wert zurück - */ -int RingBuffer::getPreviousValue(unsigned long *time) -{ - int idx = (rdIdx-1)&mask; - int ret = values[idx]; - rdIdx = (rdIdx-1)&mask; - if ((time != NULL) && (timeStamps!=NULL)) - *time = timeStamps[idx]; - if (idx != wrIdx) // rdIdx darf nicht kleiner als wrIdx werden - rdIdx = idx; - else - lastRead = 1; - return ret; -} - - -int RingBuffer::getPreviousValueDt(unsigned long *dt) -{ - int idx = (rdIdx-1)&mask; - int ret = values[idx]; - if ((dt != NULL) && (timeStamps!=NULL)) - { - unsigned long aktTime = millis(); - *dt = aktTime - timeStamps[idx]; - } - if (idx != wrIdx) // rdIdx darf nicht kleiner als wrIdx werden - rdIdx = idx; - else - lastRead = 1; - return ret; -} - - -/* - * gibt eins zurück, sobald der älteste Wert mit einer PreviousValue-Funktion - * gelesen wurde - * wird durch jeden Aufruf einer SetReadIdx-Funktion zurückgesetzt - */ -int RingBuffer::lastValueRead() -{ - return lastRead; -} - - -/* - * gibt 1 zurück, wenn rdPtr != wrPtr - * gibt 0 zurück, wenn rdPtr == wrPtr - * - * --> funktioniert nur, wenn zuvor SetReadIdx() aufgerufen wurde - */ -int RingBuffer::valueAvailable() -{ - return !lastRead; -} - - -int RingBuffer::getValueAt(int idx) -{ - return values[(wrIdx+idx)&mask]; -} - - -int RingBuffer::getValueAt(int idx, unsigned long *time) -{ - int valueIdx = (wrIdx+idx)&mask; - if ((time != NULL) && (timeStamps!=NULL)) - *time = timeStamps[valueIdx]; - return values[valueIdx]; -} - - -int RingBuffer::getPreviousValueAt(int idx) -{ - return values[(wrIdx-1-idx)&mask]; -} - - -int RingBuffer::getPreviousValueAt(int idx, unsigned long *time) -{ - int valueIdx = (wrIdx-1-idx)&mask; - if ((time != NULL) && (timeStamps!=NULL)) - *time = timeStamps[valueIdx]; - return values[valueIdx]; -} - -//***************************************************************** - - -RingBufferAverage::RingBufferAverage(int _size, int *_values, unsigned long *_timeStamps, int _averageSize):RingBuffer(_size, _values, _timeStamps) -{ - averageSize = _averageSize; - averageSum = 0; -} - -void RingBufferAverage::addValue(int val) -{ - RingBuffer::addValue(val); - averageSum += val; - if (anz > averageSize) - averageSum -= getPreviousValueAt(averageSize); -} - - -void RingBufferAverage::reset() -{ - RingBuffer::reset(); - averageSum = 0; -} - - -void RingBufferAverage::setAverageLen(int len) -{ - averageSize = len; - reset(); -} - -int RingBufferAverage::getAverage() -{ - if (anz>averageSize) - return averageSum/averageSize; - return averageSum/anz; -} - - -int RingBufferAverage::getAverageSum() -{ - return averageSum; -} - - diff --git a/STM32F3/libraries/ringbuffer/ringbuffer.h b/STM32F3/libraries/ringbuffer/ringbuffer.h deleted file mode 100644 index 3fce4c2..0000000 --- a/STM32F3/libraries/ringbuffer/ringbuffer.h +++ /dev/null @@ -1,155 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifndef RINGBUFFER_H_ -#define RINGBUFFER_H_ - -class RingBuffer { -public: - int size; // muss ZweierPotenz sein - int *values; // Pointer auf Speicher für Werte - unsigned long *timeStamps; // optional Pointer auf Speicher für ms timestamps - int rdIdx; // Leseindex - Benutzung optional - int wrIdx; // Schreibindex - int mask; - - int anz; // Aktuelle Anzahl an Werten im Puffer - int lastRead; // wird auf eins gesetz, wenn letzter vorhandener Wert gelesen wurde - - - RingBuffer(int _size, int *_values, unsigned long *_timeStamps); - - /* - * fügt einen Wert zum Ringpuffer hinzu und erzeugt einen zugehörigen Timestamp - * wenn timeStamps != NULL ist - */ - void addValue(int val); - - /* - * setzt rdIdx auf distance Werte vor den letzten Wert (wrPtr-1) - * Mit getValue können die letzten Werte bis zum letzten wert abgefragt werden - * - * gibt 1 zurück, wenn genügend Werte im Puffer sind - * gibt 0 zurück, wenn noch nicht genügend Werte im Puffer sind oder distance - * größer als die Pufferlänge ist - */ - int setReadIdx(int distance); - - /* - * Setzt rdIdx auf den ersten Wert, für den der zugehörige timeStamp mindestens zurückliegt, - * Es wird das Alter des betreffenden Wertes in ms zurückgegeben - * = wird zurückgegeben, wenn kein Wert mindestens so alt wie gefordert ist oder keine timestamps vorhanden sind - */ - int setReadIdxDt(int ms); - - /* - * gibt Wert für rdIdx zurück und incrementiert rdIdx, solange rdIdx < wrIdx - * ACHTUNG: wird wrPtr erreicht, so wird immer wieder der letzte Wert zurückgegeben! - */ - int getValue(); - - /* - * gibt Wert für rdIdx zurück, trägt den zugehörigen timestamp - * in time ein und incrementiert rdIdx, solange rdIdx < wrIdx - * ACHTUNG: wird wrPtr erreicht, so wird immer wieder der letzte Wert zurückgegeben! - */ - int getValue(unsigned long *time); - - /* - * gibt 1 zurück, wenn rdPtr != wrPtr - * gibt 0 zurück, wenn rdPtr == wrPtr - * - * --> funktioniert nur, wenn zuvor SetReadIdx() aufgerufen wurde - */ - int valueAvailable(); - - /* - * Setzt den Ringbuffer zurück - */ - void reset(); - - /* - `* decrementiert rdPtr und gibt den zugehörigen Wert zurück - */ - int getPreviousValue(); - int getPreviousValue(unsigned long *time); - - /* - `* decrementiert rdPtr und gibt den zugehörigen Wert zurück - * schreibt Zeiitdifferenz zur aktuellen Zeit in dt - */ - int getPreviousValueDt(unsigned long *dt); - - - /* - * gibt eins zurück, sobald der älteste Wert mit einer PreviousValue-Funktion - * gelesen wurde - * wird durch jeden Aufruf einer SetReadIdx-Funktion zurückgesetzt - */ - int lastValueRead(); - - /* - * Diese Funktion erlaubt den Zugriff auf den Ringbuffer wie auf ein Array. - * Der älteste Wert hat immer den Index 0, der aktuellste Wert den Index size-1 - * Der rdIdx des Puffers wird nicht verändert. - */ - int getValueAt(int idx); - int getValueAt(int idx, unsigned long *time); - - /* - * Diese Funktion erlaubt den Zugriff auf den Ringbuffer wie auf ein Array. - * Der neueste Wert hat immer den Index 0, der älteste Wert den Index size-1 - * Der rdIdx des Puffers wird nicht verändert. - */ - int getPreviousValueAt(int idx); - int getPreviousValueAt(int idx, unsigned long *time); - - -}; - - - -class RingBufferAverage : public RingBuffer -{ -public: - int averageSize; - int averageSum; - - RingBufferAverage(int _size, int *_values, unsigned long *_timeStamps, int _averageSize); - - void setAverageLen(int len); - - void addValue(int val); - void reset(); - - int getAverage(); - int getAverageSum(); - - -}; - - -#endif /* RINGBUFFER_H_ */ diff --git a/STM32F3/libraries/roboter/debug.cpp b/STM32F3/libraries/roboter/debug.cpp deleted file mode 100644 index fa0a3e7..0000000 --- a/STM32F3/libraries/roboter/debug.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include -#include "debug.h" - -#define DEBUG - -#ifndef DEBUGPORTID -#define DEBUGPORTID 2 -// TX-PIN ist PA2 -#endif - -#ifndef DEBUGPORT -#if DEBUGPORTID == 0 - #define DEBUGPORT SerialUSB -#endif -#if DEBUGPORTID == 1 - #define DEBUGPORT Serial1 -#endif -#if DEBUGPORTID == 2 - #define DEBUGPORT Serial2 -#endif -#if DEBUGPORTID == 3 - #define DEBUGPORT Serial3 -#endif -#endif - - -void debugInit() -{ -#ifdef DEBUG -#if (DEBUGPORTID != 0) - DEBUGPORT.begin(57600); -#endif - DEBUGPORT.println("Debug Init"); -#endif -} - - -static int printTimeStamp = 0; - -void debugSetTimeStamp(int OnOff) { - printTimeStamp = OnOff; -} - -static inline void addTimeStamp() { - if (printTimeStamp) { - DEBUGPORT.print(millis()); - DEBUGPORT.print(" "); - } -} - -void debugPrint(const char *s) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.println(s); -#endif -} - -void PrintNumber(const char *name, int num) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.print(name); - DEBUGPORT.print(" "); - DEBUGPORT.println(num); -#endif -} - -void PrintNumber(const char *name, byte num) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.print(name); - DEBUGPORT.print(" "); - DEBUGPORT.println(num); -#endif -} - -void PrintNumber(const char *name, float num) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.print(name); - DEBUGPORT.print(" "); - DEBUGPORT.println(num); -#endif -} - - - -void Print2Number(const char *name, int num1, int num2) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.print(name); - DEBUGPORT.print(" "); - DEBUGPORT.print(num1); - DEBUGPORT.print("\t"); - DEBUGPORT.println(num2); -#endif -} - -void Print2Number(const char *name, byte num1, byte num2) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.print(name); - DEBUGPORT.print(" "); - DEBUGPORT.print(num1); - DEBUGPORT.print("\t"); - DEBUGPORT.println(num2); -#endif -} - -void Print2Number(const char *name, float num1, float num2) -{ -#ifdef DEBUG - addTimeStamp(); - DEBUGPORT.print(name); - DEBUGPORT.print(" "); - DEBUGPORT.print(num1); - DEBUGPORT.print("\t"); - DEBUGPORT.println(num2); -#endif -} - -void PrintArray(const char *name, int len, int *arr) -{ -#ifdef DEBUG - int i; - addTimeStamp(); - DEBUGPORT.print(name); - for (i=0; i -#include -#include -#include "eeprom.h" -#include "debug.h" - - -/* - Source Code fuer 24C128 EEPROM (16Kbyte) -* - __ __ - A0 -| |- VCC - A1 -| |- WP --> unconnected low: write enabled - A2 -| |- SCL - VSS -|_____|- SDA - - -*/ - -#define EEPROM_I2C_BASE_ADDR (0xA0>>1) -#define EEPROM_I2C_ADDR(mem_addr) EEPROM_I2C_BASE_ADDR -#define EEPROM_I2C_CHANNEL I2C1 - -#define EEPROM_MAX_BUF 3 - -static uint8 msg_wr_data[EEPROM_MAX_BUF]; -static i2c_msg msg[2]; -static uint8 msg_rd_data[EEPROM_MAX_BUF]; - - -static void writeDataByte(int device_address, byte memory_address, byte data) -// write one byte of data 'data' to eeprom memory address 'memory_address' to chip with I2C address 'device_address' -{ -/* Arduino Code - Wire.beginTransmission(device_address); // device address - Wire.write(memory_address ); // memory address - Wire.write(data); // data to send - Wire.endTransmission(); // end - delay(10); -*/ - msg[0].addr = device_address; - msg[0].flags = 0; // write, 7 bit address - msg[0].xferred = 0; - msg[0].length = 3; - msg[0].data = msg_wr_data; - - msg_wr_data[0] = (memory_address>>8)&0xFF; - msg_wr_data[1] = memory_address&0xFF; - msg_wr_data[2] = data; - - i2c_master_xfer(EEPROM_I2C_CHANNEL, msg, 1, 10); - - delay(10); -} - - -static byte readDataByte(int device_address, byte memory_address) -// reads one byte of data from memory location 'memory_address' in chip at I2C address 'device_address' -{ - -/* Arduino Code - byte result; // return value - Wire.beginTransmission(device_address); // device address - Wire.write(memory_address); // memory address - Wire.endTransmission(); // end - Wire.requestFrom(device_address,1); // get one byte of data from device - if (Wire.available()) - result = Wire.read(); - return result; // return the read data byte - delay(10); -*/ - msg[0].addr = device_address; - msg[0].flags = 0; // write, 7 bit address - msg[0].xferred = 0; - msg[0].length = 2; - msg[0].data = msg_wr_data; - - msg_wr_data[0] = (memory_address>>8)&0xFF; - msg_wr_data[1] = memory_address&0xFF; - - msg[1].addr = device_address; - msg[1].flags = I2C_MSG_READ; - msg[1].xferred = 0; - msg[1].length = 1; - msg[1].data = msg_rd_data; - - i2c_master_xfer(EEPROM_I2C_CHANNEL, msg, 2, 10); - return msg_rd_data[0]; -} - -//--------------------------------------------------------------------------------- -int eepromWriteBytes(int addr, int len, unsigned char *pData) -{ - for (int i = 0; i -#include "functiontimer.h" -#include "debug.h" - - -//#define TMR_DEBUG - -typedef void (*tmrFuncPtr)(int arg); - - -typedef struct timerDaten { - struct timerDaten *pNext; - struct timerDaten *pPrev; - int time; - int state; - int arg; - int id; - tmrFuncPtr handler; -}TimerData_t; - - -TimerData_t timerArray[TIMER_ANZAHL]; -TimerData_t *pNextTimer = NULL; - - - -#define TIMEOUT_RATE 5000 // in microseconds - -HardwareTimer timer(2); - - -static void timeoutHandler() { - if (pNextTimer) { - pNextTimer->time -= 5; - if (pNextTimer->time <= 0) { -#ifdef TMR_DEBUG - PrintNumber("to", pNextTimer->id); -#endif - TimerData_t *p = pNextTimer; - pNextTimer = pNextTimer->pNext; - if (pNextTimer) - pNextTimer->pPrev = NULL; - p->state = 0; - //p->pNext = NULL; - //p->pPrev = NULL; - p->handler(p->arg); - } - } -} - -static bool timerInitialized = false; - -void timerInit() { - if (timerInitialized == false) { - for (int i=0; i= TIMER_ANZAHL) - return; - if (timerArray[id].state) // is already running? - return; - - TimerData_t *pNew = timerArray + id; - pNew->time = ms+5; - pNew->state = 1; - pNew->handler = handler; - pNew->pNext = NULL; - pNew->pPrev = NULL; - pNew->arg = arg; - if (pNextTimer == NULL) { - pNextTimer = pNew; -#ifdef TMR_DEBUG - PrintNumber("st", id); -#endif - } - else { -#ifdef TMR_DEBUG - Print2Number("sta", id, ms); -#endif - noInterrupts(); - TimerData_t *p = pNextTimer; - TimerData_t *last = NULL; - while (p) { - if (pNew->time < p->time) // vorher einhaengen - break; - else - pNew->time -= p->time; - last = p; - p = p->pNext; - } - - if (p==NULL) { - // hinter Last mit Restzeit einhängen - last->pNext = pNew; - pNew->pPrev = last; -#ifdef TMR_DEBUG - debugPrint("at end"); -#endif - } - else { // vor p einhängen und p->time um pNew->time verkleinern - p->time -= pNew->time; - pNew->pNext = p; - - if (p==pNextTimer) { - pNextTimer = pNew; - p->pPrev = pNew; -#ifdef TMR_DEBUG - PrintNumber("at begin", p->id); -#endif - } - else { - pNew->pPrev = p->pPrev; - p->pPrev = pNew; - if (pNew->pPrev) - pNew->pPrev->pNext = pNew; -#ifdef TMR_DEBUG - Print2Number("between", pNew->pPrev->id, pNew->pNext->id); -#endif - } - } - interrupts(); - } -#ifdef TMR_DEBUG - PrintTimerList(); -#endif -} - - -void timerStop(int id) { - if (id < 0) - return; - if (id>= TIMER_ANZAHL) - return; - if (timerArray[id].state==0) // is timer running? - return; - - TimerData_t *pTimer = timerArray + id; - noInterrupts(); - if (pTimer->pNext == NULL) { - // ist letzter in der queue - if (pTimer->pPrev == NULL) { - // ist einziger Timer - pTimer->state = 0; - pNextTimer = NULL; - } - else { - pTimer->pPrev->pNext = NULL; - pTimer->pPrev = NULL; - pTimer->state = 0; - } - } - else { - // Restzeit des zu löschenden Timers auf den nächsten in der Queue addieren - pTimer->pNext->time += pTimer->time; - if (pTimer == pNextTimer) {// erster Timer in der queue - pNextTimer = pTimer->pNext; - pTimer->pNext->pPrev = NULL; - pTimer->pNext = NULL; - } - else { - TimerData_t *pPrev = pTimer->pPrev; - pPrev->pNext = pTimer->pNext; - pTimer->pNext->pPrev = pPrev; - pTimer->pNext = NULL; - pTimer->pPrev = NULL; - } - } - interrupts(); - -} - - -void PrintTimerList() { - TimerData_t *p = pNextTimer; - - while (p) { - Print2Number("tmr",p->id, p->time); - if (p->pNext) - PrintNumber(" nxt", p->pNext->id); - if (p->pPrev) - PrintNumber(" prv", p->pPrev->id); - p = p->pNext; - } -} diff --git a/STM32F3/libraries/roboter/functiontimer.h b/STM32F3/libraries/roboter/functiontimer.h deleted file mode 100644 index 1a31f88..0000000 --- a/STM32F3/libraries/roboter/functiontimer.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - /* - * Das Timer-Modul stellt Funktionen bereit, mit denen andere Funktionen - * später aufgerufen werden können. Diese Funktionen sollten eine - * kurze Laufzeit haben, da sie im Interrupt aufgerufen werden. - * - * - Die Timer arbeiten mit einer Auflösung von 5 ms. - * - Es können maximal 10 Timer gleichzeitig aktiv sein. - * - Stoppen eines Timers ist möglich - * - */ - -#ifndef FUNCTION_TIMER_H_ -#define FUNCTION_TIMER_H_ - -#define TIMER_ANZAHL 10 - -typedef void (*tmrFuncPtr)(int arg); - -extern void timerInit(); -extern void timerStart(int id, int ms, tmrFuncPtr handler, int arg); -extern void timerStop(int id); - - - - -#endif /* TIMER_H_ */ diff --git a/STM32F3/libraries/roboter/motor.cpp b/STM32F3/libraries/roboter/motor.cpp deleted file mode 100644 index 57b6171..0000000 --- a/STM32F3/libraries/roboter/motor.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include -#include "motor.h" -#include "../gyro/gyro.h" -#include "debug.h" - - -#define TB6612 - -#define MOTOR_ANZ 3 - - -typedef struct { - int dir; - int pwm; - int sensor; - int led; -} MotorPins_t; - -static MotorPins_t mpins[MOTOR_ANZ]; - -#define IDX_A 0 -#define IDX_B 1 -#define IDX_C 2 - -// Umwandlung MotorIds to Index, wenn nur ein Motor addressiert ist -#define MIDX(id) ((id&OUT_A)?IDX_A:(id&OUT_B)?IDX_B:IDX_C) - - -static volatile int RadCount0; -void CountRad0() -{ - RadCount0++; -} - -static volatile int RadCount1; -void CountRad1() -{ - RadCount1++; -} - -static volatile int RadCount2; -void CountRad2() -{ - RadCount2++; -} - - -void InitMotor(int id, int PinDir, int PinPWM, int PinSensor, int PinLED) -{ - MotorPins_t *p = mpins+MIDX(id); - p->dir = PinDir; - p->pwm = PinPWM; - p->sensor = PinSensor; - p->led = PinLED; - - pinMode (p->pwm, PWM); - pinMode (p->dir, OUTPUT); - analogWrite(p->pwm, 0); - - if (p->sensor != -1) - { - if (p->led != -1) - pinMode(p->led, OUTPUT); - - pinMode(p->sensor, INPUT); - } -} - - -static inline void RadSensorAn(int motor) -{ - MotorPins_t *p = mpins; - - for (int idx=0; idxled != -1) - digitalWrite(p->led, HIGH); - if (p->sensor != -1) { - if (idx == 0) - attachInterrupt(p->sensor, CountRad0, CHANGE); - else if (idx == 1) - attachInterrupt(p->sensor, CountRad1, CHANGE); - else - attachInterrupt(p->sensor, CountRad2, CHANGE); - } - } - p++; - } - delayMicroseconds(50); // Damit ggf. ein Interrupt beim Einschalten ausgeführt wird -} - - -static inline void RadSensoren(int motor) -{ - MotorPins_t *p = mpins; - - for (int idx=0; idxled != -1) - digitalWrite(p->led, LOW); - if (p->sensor != -1) { - detachInterrupt(p->sensor); - } - } - p++; - } -} - - -void OnFwd(int Motor, int Geschwindigkeit) -{ - if(Geschwindigkeit>0) - Geschwindigkeit+=13; - else if(Geschwindigkeit<0) - Geschwindigkeit-=13; - - MotorPins_t *p = mpins; - Geschwindigkeit = constrain(Geschwindigkeit,-100, 100); // Geschwindigkeit auf Bereich -100 ... +100 begrenzen - Geschwindigkeit = (65535*Geschwindigkeit)/100; - PrintNumber("v ",Geschwindigkeit ); - - for (int i=0; i0) - { - digitalWrite(p->dir, HIGH); - v = Geschwindigkeit; - } - else - { - digitalWrite(p->dir, LOW); - v = -Geschwindigkeit; - } - analogWrite(p->pwm, v); - #endif - } - p++; - } -} - - -void OnRev(int m, int v) -{ - OnFwd(m, -v); -} - -void Off(int Motor) -{ - MotorPins_t *p = mpins; - for (int i=0; ipwm, 0); -#endif - } - p++; - } -} - - - -#if 0 - -// gyro-Funktionen nicht in diesem Modul - -void DreheRechts(int v, int Winkel) -{ - gyroResetWinkel(); - OnFwd(OUT_A, v); - OnFwd(OUT_B, -v); - while (winkelz>=-Winkel) - gyroUpdate(); - Off (OUT_AB); - -} - - -void DreheLinks(int v, int Winkel) -{ - gyroResetWinkel(); - OnFwd(OUT_A, -v); - OnFwd(OUT_B, v); - while (winkelz<=Winkel) - gyroUpdate(); - Off (OUT_AB); - -} - - -void FahreVor(int v, int Strecke) -{ - RadSensorenAn(); - RadCountR = 0; // 0 Setzen erst NACH Einschalten des Sensors, eventuell kommt schon ein Interrupt -// RadCountL = 0; - OnFwd(OUT_AB, v); - while (Strecke>RadCountR) - { -// PrintNumber("RC", RadCountR); -// delay (1); - } - Off(OUT_AB); - RadSensorenAus(); -} - -#endif - - -#if 0 -void TestRadSensoren() -{ - RadSensorenAn(); - RadCountR = 0; - RadCountL = 0; - OnFwd(OUT_AB,10); - while(1) - { - lcd.clear(); - lcd.setCursor(0,0); - lcd.print(RadCountL); - lcd.setCursor(4,0); - lcd.print(RadCountR); - delay(300); - } -} - -#endif diff --git a/STM32F3/libraries/roboter/motor.h b/STM32F3/libraries/roboter/motor.h deleted file mode 100644 index c63470e..0000000 --- a/STM32F3/libraries/roboter/motor.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - /* - * Das Modul Motor stellt Funktionen und Makros zur Steuerung der - * Fahrmotoren zur verfügung sowie Funktionen zur Steuerung und - * Abfrage der Wegsensoren. - */ - -#ifndef MOTOR_H_ -#define MOTOR_H_ - -#define OUT_A 1 -#define OUT_B 2 -#define OUT_C 4 -#define OUT_AB (OUT_A|OUT_B) -#define OUT_BC (OUT_B|OUT_C) -#define OUT_AC (OUT_A|OUT_C) -#define OUT_ABC (OUT_A|OUT_B|OUT_C) - - -extern void InitMotor(int id, int PinDir, int PinPWM, int PinSensor, int PinLED); - -extern void OnFwd(int Motor, int Geschwindigkeit); -extern void OnRev(int Motor, int Geschwindigkeit); -extern void Off (int Motor); - -#if 0 -extern void DreheRechts(int v, int Winkel); -extern void DreheLinks(int v, int Winkel); - -extern void FahreVor(int v, int Strecke); -#endif - - -#endif /* MOTOR_H_ */ diff --git a/STM32F3/libraries/roboter/sound.cpp b/STM32F3/libraries/roboter/sound.cpp deleted file mode 100644 index 09ca894..0000000 --- a/STM32F3/libraries/roboter/sound.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include -#include "sound.h" - - -/* todo */ \ No newline at end of file diff --git a/STM32F3/libraries/roboter/sound.h b/STM32F3/libraries/roboter/sound.h deleted file mode 100644 index 54c5723..0000000 --- a/STM32F3/libraries/roboter/sound.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifndef SOUND_H_ -#define SOUND_H_ - - - - -#endif /* SOUND_H_ */ diff --git a/STM32F3/libraries/roboter/ultraschall.cpp b/STM32F3/libraries/roboter/ultraschall.cpp deleted file mode 100644 index 871c6ac..0000000 --- a/STM32F3/libraries/roboter/ultraschall.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ -#include -#include "ultraschall.h" -#include "debug.h" - -/* - * Für jeden Ultraschallsensor gibt es eine Struktur USSensor, die im Array USSensoren - * angelegt wird. - * Für jeden Sensor muss einmal die Funktion addUSSensor() mit den richtigen Anschluss - * Pins aufgerufen werden. - * - * Zum Messen muss ein Sensor aktiviert werden. Es können alle Sensoren aktiv sein. - * Sie werden dann abwechselnd für Messungen getriggert. Nicht mehr benötigte Sensoren - * sollten deaktiviert werden. - * Im aktiven Zustand wird durch die Funktion UltraschallMessen() die Messung - * jeweils eines aktiven Sensors gestartet, wenn keine Messung aktiv ist. - * UltraschallMessen() koordiniert nur die Messungen (es darf immer nur ein - * Ultraschallsensor aktiv sein) und wartet nicht, bis die Messung erfolgt ist. - * UltraschallMessen sollte alle 25ms oder kürzer aufgerufen werden, - * wenn Ultraschallmesswerte benötigt werden. - * --> ggf. Aktivieren der nächsten Messung im Interrupt? --> testen - * - * Das Messen selbst erfolgt asynchron zur Programmausführung. Eine spezielle - * Messroutine wird aufgerufen, wenn der Echo-Pin des Sensors seinen Zustand ändert. - * Diese Routine trägt die gemessene Entfernung und einen Zeitstempel in die Sensor- - * struktur ein und setzt ein Flag in der Struktur, dass ein neuer Messwert zur - * Verfügung steht. - * - * Mit der Funktion UltraschallMessenFertig(id) kann abgefragt werden, ob ein neuer - * Messwert vorliegt. Dieser kann mit UltraschallMesswert(id) abgefragt werden. - * Mit UltraschallMesswertAlter(id) kann abgefragt werden, wie alt der ausgelesene - * Messwert ist. Alternativ zu den Funktionsaufrufen können die Werte auch direkt aus - * den Sensorstrukturen ausgelesen werden. - * - * Alternativ zum automatischen Messen im Hintergrund kann statt UltraschallMessen() - * die Funktion UltraschallMessenEinzel(id) aufgerufen werden. Diese Funktion blockiert - * solange bis ein Messwert vorliegt (max. 50ms falls kein Wert ermittelt werden kann) - * und gibt diesen zurück. Eine Aktivierung des Sensors ist nicht erforderlich. - * Eventuell laufende Messungen werden abgebrochen. Eine noch laufende Messung wird - * jedoch zu Ende geführt. - * - * Zeitüberwachung: - * Es kann eine maximale Laufzeit für das zu erwartende Echo gesetzt werden (z.B. 30ms). - * Für diese Laufzeit wird ein Timer mit eigenem Interrupt gestartet. - * Gestoppt wird der Timer, wenn die Echo-Interrupt-Funktion vor Ablauf des Timers ausgeführt wird - * (der Echo-Puls ist in diesem Fall innerhalb des zulässigen Zeitfensters gekommen. - * Läuft der Timer ab, ist die aktuelle Messung ungültig und es wird versucht eine neue Messung - * mit dem nächsten Sensor zu starten. - * Eine Messung kann nur gestartet werden, wenn der Echo-Pin auf LOW ist. - * Gibt es keinen Sensor, der bei Startanforderung echo==LOW hat, so wird nichts unternommen und - * auf die nächste fallende Flanke einer Echo-Leitung (Interrupt) gewartet. Die fallende Flanke startet - * dann eine neue Messung per Interrupt. - * Gibt es einen Sensor, der bereit für eine neue Messung ist, so wird bei diesem die Messung - * gestartet. - * Damit das funktioniert, muss für jeden Echo-Pin eine eigene Interrupt-Funktion attached werden. - * - * Wenn auf die Zeitüberwachung verzeichtet wird blockiert eine ungültige Messung weitere Messungen - * anderer Sensoren um die Zeit bis zum HIGH-LOW-Übergang des Echopins - * --> bei nur einem Sensor ist eine Zeitüberwachung nicht nötig, da kein Neustart einer Messung - * stattfinden kann bevor der Echo-Pin wieder Low ist. - * - * HC-SR04: Wenn kein Echo kommt, wird das ECHO-Signal nach ca. 235ms (entspricht ca. 4m) wieder nach - * LOW gezogen. - * - * Um das Suchen nach einem messbereiten Sensor zu vereinfachen werden die aktiven Sensorstrukturen in einer - * doppelt verketteten Liste verwaltet. - * - * Der Aufruf von micros() im Interrupt funktioniert nicht sicher, deshalb muss die Timing-Information auf anderm Wege - * beschafft werden: - * Eigener Hardwaretimer für Ultraschallsensoren (ist auch schneller bei der Vewaltung) - * - */ - - -#define IDLE_CHECK_TMO 25 // ms - -// global state -#define US_GLOBAL_IDLE 0 -#define US_GLOBAL_MESSUNG_AKTIV 1 - -static int state = US_GLOBAL_IDLE; - -// Prototypen -static void TimerIntRangeTimeout(); -static void TimerIntWaitIdle(); -static inline void startMessung(); -static void USInt(); - -// globale Variablen -USSensor USSensoren[MAX_US_SENSOR]; - -// static Variablen -static USSensor *pAktiverSensor = NULL; -static int SensorAktivAnzahl=0; -static int MessPause = 0; - - -//-------------------------------------------------------------------------- -// Timer-Funktionen -//-------------------------------------------------------------------------- - -static HardwareTimer usTimer(15); -static int usTimerCount; // Beim Starten wird sofort ein Interrupt ausgelöst, - // der ausgeblendet werden muss - - -static void startUsTimer(int ms, voidFuncPtr handler) -{ - usTimer.pause(); - - // Set up period - usTimer.setPeriod(ms*1000); // in microseconds - - usTimerCount = 1; - - // Set up an interrupt on channel 1S - usTimer.setChannel1Mode(TIMER_OUTPUT_COMPARE); - usTimer.setCompare(TIMER_CH1, 1); // Interrupt 1 count after each update - usTimer.attachCompare1Interrupt(handler); - - // Refresh the timer's count, prescale, and overflow - usTimer.refresh(); - - // Start the timer counting - usTimer.resume(); -} - - -static void stopUsTimer() { - usTimer.pause(); -} - -//-------------------------------------------------------------------------- - - - -/** - * Startet die Messung beim nächsten IDLE-Sensor. - * Wenn keine Messung aktiv ist (US_GLOBAL_IDLE) und kein Sensor gefunden wird, - * wird der IDLE-Wait-Timer gestartet - */ -static inline void startMessung() -{ - if (state != US_GLOBAL_IDLE) - return; // Es kann keine Messung gestartet werden - - int anz = SensorAktivAnzahl; - - while (anz) { - pAktiverSensor = pAktiverSensor->pNext; // erstmal auf den nächsten Sensor stellen - if (pAktiverSensor->state==US_IDLE) - { - //PrintNumber(" nis", pAktiverSensor->id); - // nur wenn EchoPin Low ist, kann die nächste Messung erfolgen - if (digitalRead(pAktiverSensor->echoPin) == LOW) { - state = US_GLOBAL_MESSUNG_AKTIV; // globalen Zustand setzen - pAktiverSensor->state = US_ACTIVE; - //PrintNumber("sel", pAktiverSensor->id); - digitalWrite(pAktiverSensor->triggerPin, HIGH); - delayMicroseconds(10); // FIXME: funktioniert das im Interrupt ??? - // sollte gehen, ist eine Assemblerschleife - // muss aber mal gemessen werden!! - digitalWrite(pAktiverSensor->triggerPin, LOW); - attachInterrupt(pAktiverSensor->echoPin, USInt, CHANGE); - return; - } - //else - //PrintNumber("ns2", pAktiverSensor->id); - } - //else - // PrintNumber("ns1", pAktiverSensor->id); - - anz--; - } - startUsTimer(IDLE_CHECK_TMO, TimerIntWaitIdle); -} - -// Interrupt-Routinen - -/** - * Interrupt-Routine für Echo-Pin - */ -static void USInt() -{ - int time = usTimer.getCount(); - int pin = digitalRead(pAktiverSensor->echoPin); - if (pin==HIGH) - { - if (pAktiverSensor->state == US_ACTIVE) { - startUsTimer(pAktiverSensor->maxTime, TimerIntRangeTimeout); - //PrintNumber(" eh",pSensor->id); - } - } - else - { - stopUsTimer(); - detachInterrupt(pAktiverSensor->echoPin); - pAktiverSensor->entfernung = time/pAktiverSensor->timerTicksPerCm; - //Print2Number("usi", pAktiverSensor->id, pAktiverSensor->entfernung); - pAktiverSensor->messZeit = millis(); - pAktiverSensor->lastValidRange = pAktiverSensor->entfernung; - pAktiverSensor->lastValidTime = pAktiverSensor->messZeit; - pAktiverSensor->neuerMesswert = 1; - pAktiverSensor->state = US_IDLE; - state = US_GLOBAL_IDLE; - if (pAktiverSensor->handler) - pAktiverSensor->handler(pAktiverSensor->id, pAktiverSensor->entfernung); - if (MessPause) - startUsTimer(MessPause, TimerIntWaitIdle); - else - startMessung(); - } -} - -static void TimerIntWaitIdle() { - if (usTimerCount) - usTimerCount--; - else { - //debugPrint("twi"); - stopUsTimer(); - startMessung(); - } -} - -static void TimerIntRangeTimeout() { - if (usTimerCount) - usTimerCount--; - else { - stopUsTimer(); - if (pAktiverSensor) { - detachInterrupt(pAktiverSensor->echoPin); - //debugPrint(" tmo"); - if (pAktiverSensor->state == US_ACTIVE) { - pAktiverSensor->state = US_IDLE; - state = US_GLOBAL_IDLE; // Es kann eine Messung mit einem anderen Sensor gestartet werden - pAktiverSensor->entfernung = ENTFERNUNG_INVALID; - pAktiverSensor->messZeit = millis(); - if (pAktiverSensor->handler) - pAktiverSensor->handler(pAktiverSensor->id, pAktiverSensor->entfernung); - startMessung(); - } - else - { - if (state == US_GLOBAL_IDLE) - startMessung(); - } - } - } -} - - -//----------------------------------------------------------------- -// extern aufrufbare Funktionen -//----------------------------------------------------------------- - -/** - * Definiert und initialisiert einen Ultraschallsensor - * maxRange in cm - */ -void addUSSensor(int id, int trigger, int echo, int maxRange) -{ - if ((id < 0) || (id >= MAX_US_SENSOR)) - return; - USSensor *pSensor = &USSensoren[id]; - pSensor->triggerPin = trigger; - pSensor->echoPin = echo; - pSensor->enabled = 0; - pSensor->state = US_IDLE; - pSensor->id = id; - pSensor->maxTime = (maxRange*US_ROUNDTRIP_CM)/1000; - - // Timer-Wertebereich für maxRange ermitteln - usTimer.setPeriod(pSensor->maxTime*1000); // in microseconds - pSensor->timerTicksPerCm = usTimer.getOverflow()/maxRange; - - // pins initialisieren - pinMode(trigger, OUTPUT); - pinMode(echo, INPUT); -} - -/** - * aktiviert einen Sensor zum Messen im Hintergrund - */ -void aktiviereUSSensor(int id) -{ - if (USSensoren[id].enabled) // ist bereits enabled - return; - - USSensoren[id].enabled = 1; - - if (pAktiverSensor == NULL) { // ist der erste Sensor - pAktiverSensor = USSensoren + id; - pAktiverSensor->pNext = pAktiverSensor; // zeigt auf sich selbst! - pAktiverSensor->pPrev = pAktiverSensor; - SensorAktivAnzahl = 1; - // Über den Timer wird erreicht, dass die Messung gestartet wird. - startUsTimer(IDLE_CHECK_TMO, TimerIntWaitIdle); - } - else { - noInterrupts(); - USSensor *pSensor = USSensoren + id; - pSensor->state = US_IDLE; - - pSensor->pNext = pAktiverSensor->pNext; - pSensor->pPrev = pAktiverSensor; - pAktiverSensor->pNext->pPrev = pSensor; - pAktiverSensor->pNext = pSensor; - - SensorAktivAnzahl++; - interrupts(); - } -} - - -void UsAttachHandler(int id, usFuncPtr fkt){ - USSensoren[id].handler = fkt; -} - - -void UsSetMessPause(int ms) { - MessPause = ms; -} - - -/** - * deaktiviert einen Sensor - */ -void deaktiviereUSSensor(int id) -{ - /* - * Problem: - * für den aktuellen Sensor könnte aktuell eine Messung laufen! - */ - if (!USSensoren[id].enabled) - return; - - noInterrupts(); - USSensor *pSensor = USSensoren + id; - pSensor->enabled = 0; - pSensor->neuerMesswert = 0; - - if (SensorAktivAnzahl>1) { - pSensor->pPrev->pNext = pSensor->pNext; - pSensor->pNext->pPrev = pSensor->pPrev; - if (pAktiverSensor == pSensor) - pAktiverSensor = pSensor->pNext; - } - else - pAktiverSensor = NULL; - - SensorAktivAnzahl--; - - if (pSensor->state == US_ACTIVE) { - detachInterrupt(pSensor->echoPin); - pSensor->state = US_IDLE; - state = US_GLOBAL_IDLE; - - if (SensorAktivAnzahl) - // Über den Timer wird erreicht, dass eine neue Messung gestartet wird. - startUsTimer(IDLE_CHECK_TMO, TimerIntWaitIdle); - } - interrupts(); -} - -/** - * gibt 1 zurück, wenn ein neuer Messwert vorliegt. - * Es wird nur einmal eine 1 zurückgegeben, das Flag wird beim Auslesen zurückgesetzt - */ -int UltraschallMessenFertig(int id) -{ - if (USSensoren[id].neuerMesswert) - { - USSensoren[id].neuerMesswert = 0; - return 1; - } - return 0; -} - - -/** - * gibt aktuellstes Messergebnis zurück - */ -int16 UsAktuellerMesswert(int id) -{ - return USSensoren[id].entfernung; -} - -/** - * Gibt das Alter der aktuellsten Messung in ms zurück - */ -int UsAktuellerMesswertAlter(int id) -{ - return (millis() - USSensoren[id].messZeit); -} - -/** - * gibt den letzten gueltigen Wert zurück - */ -int16 UsLetzterGueltigerMesswert(int id) -{ - return USSensoren[id].lastValidRange; -} - -/** - * Gibt das Alter der letzten Messung in ms zurück - */ -int UsLetzterGueltigerMesswertAlter(int id) -{ - return (millis() - USSensoren[id].lastValidTime); -} - - -/** - * ----------------------------------------------------------- - * blockierende Messung - * ----------------------------------------------------------- - */ -int16 UltraschallMessenEinzel(int id) -{ - uint32 t1; - uint32 t2=0; - if ((id<0) || (id >= MAX_US_SENSOR)) - return ENTFERNUNG_INVALID; - - // alle Sensoren deaktivieren - for (int i=0; iechoPin) == HIGH ) - { - t2 = micros(); - if (t2-t1 > 100000) // Wenn 100ms lang kein LOW am Echo-Pin Fehler zurückgeben - return ERROR_SENSOR_BUSY; - } - - // trigger-Impuls generieren - digitalWrite(pSensor->triggerPin, HIGH); - delayMicroseconds(10); - digitalWrite(pSensor->triggerPin, LOW); - - // auf HIGH am Echo-Pin warten - t1 = micros(); - - while (digitalRead(pSensor->echoPin) == LOW ) - { - t2 = micros(); - if (t2-t1 > 1000) - return ERROR_NO_SENSOR; // kein LOW-HIGH-Übergang innerhalb 1ms detektiert -> Fehler - } - t1 = micros(); - - // auf LOW am Echo-Pin warten - while (digitalRead(pSensor->echoPin) == HIGH ) - { - t2 = micros(); - if ((t2-t1) > (uint32)(pSensor->maxTime*1000)) - return ENTFERNUNG_INVALID; // Messentfernung größer maxRange - } - - return (t2-t1)/US_ROUNDTRIP_CM; -} - - -//------------------------------------------------------------------------ -void PrintUsSensorList() { - USSensor *pSensor = pAktiverSensor; - - for (int i = 0; i < SensorAktivAnzahl; i++){ - if (pSensor == NULL) - return; - PrintNumber("Sensor", pSensor->id); - if (pSensor->pNext == NULL) - debugPrint(" next NULL"); - else - PrintNumber(" next", pSensor->pNext->id); - if (pSensor->pPrev == NULL) - debugPrint(" prev NULL"); - else - PrintNumber(" prev", pSensor->pPrev->id); - pSensor = pSensor->pNext; - } -} - -#if 0 -// Timer Test-Funktionen - -static void testHandler() { - debugPrint("usi"); - - if (usTimerCount) - usTimerCount--; - else { - stopUsTimer(); - debugPrint("---"); - startUsTimer(300, testHandler); - } -} - -void TestUsTimer() { - startUsTimer(100, testHandler); -} - -int GetUsTimerCount() { - return usTimer.getCount(); -} -#endif - diff --git a/STM32F3/libraries/roboter/ultraschall.h b/STM32F3/libraries/roboter/ultraschall.h deleted file mode 100644 index a03af40..0000000 --- a/STM32F3/libraries/roboter/ultraschall.h +++ /dev/null @@ -1,156 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2015 Frank-Michael Krause - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifndef ULTRASCHALL_H_ -#define ULTRASCHALL_H_ - -#define US_IDLE 0 -#define US_ACTIVE 1 - - -#define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. - -typedef void (*usFuncPtr)(int id, int entfernung); - -typedef struct USSensor_s { - int8 id; - int triggerPin; - int echoPin; - int8 enabled; - int8 state; // IDLE, ACTIVE - int8 neuerMesswert; - int16 maxTime; //Zeit für maximal zu messende Entfernung in ms - int timerTicksPerCm; - int16 entfernung; // in cm - uint32 messZeit; // Systemzeit der Messung in ms - int16 lastValidRange; - uint32 lastValidTime; -// uint32 startZeit; // Startzeit der aktuellen Messung - usFuncPtr handler; - struct USSensor_s *pNext; - struct USSensor_s *pPrev; -} USSensor; - -#define MAX_US_SENSOR 4 - -#define ENTFERNUNG_INVALID -1 -#define ERROR_NO_SENSOR -2 -#define ERROR_SENSOR_BUSY -3 - -extern USSensor USSensoren[MAX_US_SENSOR]; - - -/***************************************************** - * Funktionen zur Initialisierung - ****************************************************/ - -/** - * id: Index zwischen 0 und MAX_US_SENSOR-1 - * trigger: IO-Pin, der mit dem Trigger-Eingang des Sensors verbunden ist - * echo: IO-Pin, der mit dem Echo-Ausgang des Sensors verbunden ist. - * !!! der Echo-IO-Pin muss 5V tolerant sein oder mit einem - * Spannungsteiler versehen werden. - * maxRange: Maximal zu messende Entfernung in cm; optional - */ -extern void addUSSensor(int id, int trigger, int echo, int maxRange=150); - -/** - * setzt die Zeit der Pause, die nach erfolgreicher Messung vor der nächsten - * Messung eingefügt wird. - * Default ist 0, d.h. keine Pause - */ -extern void UsSetMessPause(int ms); - - - -/***************************************************** - * Funktionen für blockierende Messung - * Bei Aufruf der blockierenden Einzelmessfunktion werden - * alle über Interrupt akktivierten Sensoren deaktiviert - * - * gibt Entfernung in cm zurück - * bzw. die Fehlerwerte - * ENTFERNUNG_INVALID -1 - * ERROR_NO_SENSOR -2 - * ERROR_SENSOR_BUSY -3 - *****************************************************/ -extern int16 UltraschallMessenEinzel(int id); - - - - -/***************************************************** - * Funktionen für nicht blockierende, interrupt-basierte Messung - * - * Durch Zustandsvariablen gesteuert werden auf allen aktiven Sensoren - * immer wieder abwechselnd Messungen angestossen. - * Die Messergebnisse werden in Variablen der Sensorstruktur abgelegt - * und können über Funktionen aus dem Hauptptogramm abgefragt werden. - * - * Es kann pro Sensor eine Handler-Funktion registriert werden, - * die aufgerufen wird, sobald ein neuer Messwert vorliegt. - *****************************************************/ - - -extern void aktiviereUSSensor(int id); -extern void deaktiviereUSSensor(int id); - -extern void UsAttachHandler(int id, usFuncPtr fkt); - - -/** - * gibt das Ergebnis der letzten Messung zurück. - * Kann ENTFERNUNG_INVALID sein. - */ -extern int16 UsAktuellerMesswert(int id); - -/** - * gibt das Alter des letzen Messergebnisses in ms an. - */ -extern int UsAktuellerMesswertAlter(int id); - -/** - * gibt den letzten Messwert des Sensors zurück, der nicht - * ENTFERNUNG_INVALID ist. - */ -extern int16 UsLetzterGueltigerMesswert(int id); - - -/** - * gibt das Alter des letzen gültigen Messergebnisses in ms an. - */ -extern int UsLetzterGueltigerMesswertAlter(int id); - - - -/***************************************************** - * Debug-Funktionen - ****************************************************/ - -extern void PrintUsSensorList(); - - -#endif /* ULTRASCHALL_H_ */ diff --git a/STM32F3/platform.txt b/STM32F3/platform.txt deleted file mode 100644 index 3218f85..0000000 --- a/STM32F3/platform.txt +++ /dev/null @@ -1,144 +0,0 @@ -# -# -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=STM32F3 boards -version=0.1.0 - -# compiler variables -# ---------------------- -#build.gcc_ver=gcc-arm-none-eabi-4.8.3-2014q1 - -compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/ -compiler.c.cmd=arm-none-eabi-gcc -compiler.c.flags=-c -g -Os -w -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} -compiler.c.elf.cmd=arm-none-eabi-g++ -compiler.c.elf.flags=-Os -Wl,--gc-sections -compiler.S.cmd=arm-none-eabi-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -compiler.cpp.cmd=arm-none-eabi-g++ -compiler.cpp.flags=-c -g -Os -w -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} -compiler.ar.cmd=arm-none-eabi-ar -compiler.ar.flags=rcs -compiler.objcopy.cmd=arm-none-eabi-objcopy -compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 -compiler.elf2hex.flags=-O binary -compiler.elf2hex.cmd=arm-none-eabi-objcopy -compiler.ldflags= -compiler.size.cmd=arm-none-eabi-size -compiler.define=-DARDUINO= - -# this can be overriden in boards.txt -build.cpu_flags= -build.hs_flag= -build.common_flags= -build.extra_flags= {build.cpu_flags} {build.hs_flag} {build.common_flags} - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags="-L{build.variant.path}/ld" -compiler.cpp.extra_flags= -compiler.S.extra_flags= -compiler.ar.extra_flags= -compiler.elf2hex.extra_flags= - - - -compiler.libs.c.flags="-I{build.core.path}/libmaple" "-I{build.core.path}/libmaple/include" "-I{build.core.path}/libmaple/stm32f3/include" "-I{build.core.path}/libmaple/usb" "-I{build.core.path}/libmaple/usb/usb_lib" "-I{build.core.path}/wirish/include" "-I{build.core.path}/wirish" -#compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" "-I{build.system.path}/wirish/include" - - -#compiler.libs.c.flags="-I{build.core.path}/libmaple" -I{build.core.path}/libmaple/usbF4 -I{build.core.path}/libmaple/usbF4/STM32_USB_Device_Library/Core/inc -I{build.core.path}/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc -I{build.core.path}/libmaple/usbF4/STM32_USB_OTG_Driver/inc -I{build.core.path}/libmaple/usbF4/VCP - - - -# USB Flags -# --------- -## build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' - -# Default usb manufacturer will be replaced at compile time using -# numeric vendor ID if available or by board's specific value. -## build.usb_manufacturer="Unknown" - - -# build patterns -# --------------------- - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" -#recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" - -## Combine gc-sections, archives, and objects -##recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -#-Wl,--entry=__start__ -#recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} -Wl,--whole-archive "{build.path}/{archive_file}" -Wl,--no-whole-archive -Wl,--end-group - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -#recipe.size.regex=\.text\s+([0-9]+).* -recipe.size.regex=^(?:\.text|\.rodata|\.ARM.exidx)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* - -# Uploader tools -# ------------------- - -# Upload using Maple bootloader over DFU -tools.maple_upload.cmd=maple_upload -tools.maple_upload.cmd.windows=maple_upload.bat -#tools.maple_upload.cmd.linux= -tools.maple_upload.path={runtime.hardware.path}/tools/win -tools.maple_upload.path.macosx={runtime.hardware.path}/tools/macosx - -tools.maple_upload.upload.params.verbose=-d -tools.maple_upload.upload.params.quiet= -tools.maple_upload.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" - -# Generic STM32 upload via serial to Serial Port 1 (pins PA9 and PA10) - note. Boot0 line needs to high on board reset to enable upload via serial -# at the end of the upload the program is automatically run, without the board being reset - -tools.serial_upload.cmd=serial_upload -tools.serial_upload.cmd.windows=serial_upload.bat -#tools.serial_upload.cmd.linux= -tools.serial_upload.path={runtime.hardware.path}/tools/win - -tools.serial_upload.upload.params.verbose=-d -tools.serial_upload.upload.params.quiet= -tools.serial_upload.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" - -# -tools.upload_router.cmd=upload_router -tools.upload_router.cmd.windows=upload_router.bat -#tools.upload_router.cmd.linux= -tools.upload_router.path={runtime.hardware.path}/tools/win - -tools.upload_router.upload.params.verbose=-d -tools.upload_router.upload.params.quiet= -tools.upload_router.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}" {upload.protocol} {build.debuggingMode} "{runtime.ide.path}/hardware/tools/{build.gcc_ver}/bin/" - -# STLINK/V2 - -tools.stlink.cmd=stlink -tools.stlink.cmd.windows=stlink_upload.bat -#tools.stlink.cmd.linux= -tools.stlink.path={runtime.hardware.path}/tools/win -tools.stlink.upload.params.verbose=-d -tools.stlink.upload.params.quiet= -tools.stlink.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" - diff --git a/STM32F3/variants/discovery_f3/board/board.h b/STM32F3/variants/discovery_f3/board/board.h deleted file mode 100644 index 179dede..0000000 --- a/STM32F3/variants/discovery_f3/board/board.h +++ /dev/null @@ -1,138 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/boards/48F3/include/board/board.h - * @author F3-port: Hanspeter Portner - * @brief F303xx board header (F303CB, F303CC, F303RB, F303RC, F303VB, F303VC). - * - * See wirish/boards/maple/include/board/board.h for more information - * on these definitions. - */ - -#ifndef _BOARD_F303xx_H_ -#define _BOARD_F303xx_H_ - -#include - -#define CYCLES_PER_MICROSECOND 72 -#define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */ - -enum { - PC13, PC14, PC15, - PF0, PF1, - PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, - PB0, PB1, PB2, - PB10, PB11, PB12, PB13, PB14, PB15, - PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15, - PB3, PB4, PB5, PB6, PB7, PB8, PB9, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - PC0, PC1, PC2, PC3, - PF4, - PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, - PD2, -# if defined(STM32_XL_DENSITY) - PE2, PE3, PE4, PE5, PE6, - PF9, PF10, - PF2, - PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15, - PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15, - PF6, - PD0, PD1, - PD3, PD4, PD5, PD6, PD7, - PE0, PE1, -# endif -#endif -}; - -#define BOARD_USART1_TX_PIN PA9 /* also PB6 */ -#define BOARD_USART1_RX_PIN PA10 /* also PB7 */ - -#define BOARD_USART2_TX_PIN PA2 /* also PA14, PB3 */ -#define BOARD_USART2_RX_PIN PA3 /* also PA15, PB4 */ - -#define BOARD_USART3_TX_PIN PB10 -#define BOARD_USART3_RX_PIN PB11 - -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -# define BOARD_UART4_TX_PIN PC10 -# define BOARD_UART4_RX_PIN PC11 - -# define BOARD_UART5_TX_PIN PC12 -# define BOARD_UART5_RX_PIN PD2 -#endif - -#define BOARD_NR_SPI 3 - -#define BOARD_SPI1_NSS_PIN PA4 -#define BOARD_SPI1_SCK_PIN PA5 -#define BOARD_SPI1_MISO_PIN PA6 -#define BOARD_SPI1_MOSI_PIN PA7 - -#define BOARD_SPI2_NSS_PIN PB12 -#define BOARD_SPI2_SCK_PIN PB13 -#define BOARD_SPI2_MISO_PIN PB14 -#define BOARD_SPI2_MOSI_PIN PB15 - -#define BOARD_SPI3_NSS_PIN PA15 -#define BOARD_SPI3_SCK_PIN PB3 -#define BOARD_SPI3_MISO_PIN PB4 -#define BOARD_SPI3_MOSI_PIN PB5 - -#define BOARD_JTMS_SWDIO_PIN PA13 -#define BOARD_JTCK_SWCLK_PIN PA14 -#define BOARD_JTDI_PIN PA15 -#define BOARD_JTDO_PIN PB3 -#define BOARD_NJTRST_PIN PB4 - -#if defined(STM32_MEDIUM_DENSITY) -# define BOARD_NR_USARTS 3 -# define BOARD_NR_GPIO_PINS 37 -# define BOARD_NR_PWM_PINS 28 -# define BOARD_NR_ADC_PINS 15 -# define BOARD_NR_USED_PINS 4 -#elif defined(STM32_HIGH_DENSITY) -# define BOARD_NR_USARTS 5 -# define BOARD_NR_GPIO_PINS 52 -# define BOARD_NR_PWM_PINS 32 -# define BOARD_NR_ADC_PINS 22 -# define BOARD_NR_USED_PINS 4 -#elif defined(STM32_XL_DENSITY) -# define BOARD_NR_USARTS 5 -# define BOARD_NR_GPIO_PINS 87 -# define BOARD_NR_PWM_PINS 53 -# define BOARD_NR_ADC_PINS 39 -# define BOARD_NR_USED_PINS 7 -#endif - -/* redefine the following ones to match your hardware design */ -#define BOARD_BUTTON_PIN PA0 -#define BOARD_LED_PIN PE10 - -#define BOARD_USB_DISC_DEV GPIOA -#define BOARD_USB_DISC_BIT 13 - -#endif diff --git a/STM32F3/variants/discovery_f3/discovery_f3.cpp b/STM32F3/variants/discovery_f3/discovery_f3.cpp deleted file mode 100644 index c3c2542..0000000 --- a/STM32F3/variants/discovery_f3/discovery_f3.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2013 OpenMusicKontrollers. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/boards/48F3/board.c - * @author F3-port: Hanspeter Portner - * @brief F303xx board file (F303CB, F303CC, F303RB, F303RC, F303VB, F303VC). - */ - -#include "board/board.h" - -#include "libmaple/gpio.h" -#include "libmaple/timer.h" - -#include "wirish/wirish_debug.h" -#include "wirish/wirish_types.h" - -/* Since we want the Serial Wire/JTAG pins as GPIOs, disable both SW - * and JTAG debug support on the packages with low pin-count (e.g. MEDIUM_DENSITY), - * unless configured otherwise. */ -void boardInit(void) { -#if defined(STM32_MEDIUM_DENSITY) - //disableDebugPorts(); -#endif - enableDebugPorts(); - -} - -extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { - [PC13]= {GPIOC, NULL, NULL, 13, 0, ADCx}, /* PC13 */ - [PC14]= {GPIOC, NULL, NULL, 14, 0, ADCx}, /* PC14 */ /* OSC32_IN */ - [PC15]= {GPIOC, NULL, NULL, 15, 0, ADCx}, /* PC15 */ /* OSC32_OUT */ - - [PF0] = {GPIOF, NULL, NULL, 0, 0, ADCx}, /* PF0 */ /* OSC_IN */ - [PF1] = {GPIOF, NULL, NULL, 1, 0, ADCx}, /* PF1 */ /* OSC_OUT */ - - [PA0] = {GPIOA, TIMER2, ADC1, 0, 1, 1}, /* PA0 */ - [PA1] = {GPIOA, TIMER2, ADC1, 1, 2, 2}, /* PA1 */ - [PA2] = {GPIOA, TIMER2, ADC1, 2, 3, 3}, /* PA2 */ /* also TIMER15 CH1 */ - [PA3] = {GPIOA, TIMER2, ADC1, 3, 4, 4}, /* PA3 */ /* also TIMER15 CH2 */ - [PA4] = {GPIOA, TIMER3, ADC2, 4, 2, 1}, /* PA4 */ - [PA5] = {GPIOA, NULL, ADC2, 5, 0, 2}, /* PA5 */ - [PA6] = {GPIOA, TIMER3, ADC2, 6, 1, 3}, /* PA6 */ /* also TIMER16 CH1 */ - [PA7] = {GPIOA, TIMER3, ADC2, 7, 2, 4}, /* PA7 */ /* also TIMER17 CH1 */ - - [PB0] = {GPIOB, TIMER3, ADC3, 0, 3, 12}, /* PB0 */ - [PB1] = {GPIOB, TIMER3, ADC3, 1, 4, 1}, /* PB1 */ - [PB2] = {GPIOB, NULL, ADC2, 2, 0, 12}, /* PB2 */ - - [PB10]= {GPIOB, TIMER2, NULL, 10, 3, ADCx}, /* PB10 */ - [PB11]= {GPIOB, TIMER2, NULL, 11, 4, ADCx}, /* PB11 */ - [PB12]= {GPIOB, NULL, ADC4, 12, 0, 3}, /* PB12 */ - [PB13]= {GPIOB, NULL, ADC3, 13, 0, 5}, /* PB13 */ - [PB14]= {GPIOB, TIMER15,ADC4, 14, 1, 4}, /* PB14 */ - [PB15]= {GPIOB, TIMER15,ADC4, 15, 2, 5}, /* PB15 */ - - [PA8] = {GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* PA8 */ - [PA9] = {GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* PA9 */ /* also TIMER2_CH3 */ - [PA10]= {GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* PA10 */ /* also TIMER2 CH4 */ - [PA11]= {GPIOA, TIMER4, NULL, 11, 1, ADCx}, /* PA11 */ /* also TIMER1 CH4 */ - [PA12]= {GPIOA, TIMER4, NULL, 12, 2, ADCx}, /* PA12 */ /* also TIMER16 CH1 */ - [PA13]= {GPIOA, TIMER4, NULL, 13, 3, ADCx}, /* PA13 */ - [PA14]= {GPIOA, TIMER8, NULL, 14, 2, ADCx}, /* PA14 */ - [PA15]= {GPIOA, TIMER8, NULL, 15, 1, ADCx}, /* PA15 */ - - [PB3] = {GPIOB, TIMER2, NULL, 3, 2, ADCx}, /* PB3 */ - [PB4] = {GPIOB, TIMER3, NULL, 4, 1, ADCx}, /* PB4 */ /* also TIMER16 CH1 */ - [PB5] = {GPIOB, TIMER3, NULL, 5, 2, ADCx}, /* PB5 */ /* also TIMER17 CH1 */ - [PB6] = {GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* PB6 */ /* also TIMER8 CH1 */ - [PB7] = {GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* PB7 */ /* also TIMER3 CH4 */ - [PB8] = {GPIOB, TIMER4, NULL, 8, 3, ADCx}, /* PB8 */ /* also TIMER16 CH1 */ - [PB9] = {GPIOB, TIMER4, NULL, 9, 4, ADCx}, /* PB9 */ /* also TIMER17 CH1 */ - -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - [PC0] = {GPIOC, NULL, ADC1, 0, 0, 6}, /* PC0 */ - [PC1] = {GPIOC, NULL, ADC1, 1, 0, 7}, /* PC1 */ - [PC2] = {GPIOC, NULL, ADC1, 2, 0, 8}, /* PC2 */ - [PC3] = {GPIOC, NULL, ADC1, 3, 0, 9}, /* PC3 */ - - [PF4] = {GPIOF, NULL, ADC1, 4, 0, 5}, /* PF4 */ - - [PC4] = {GPIOC, NULL, ADC2, 4, 0, 5}, /* PC4 */ - [PC5] = {GPIOC, NULL, ADC2, 5, 0, 11}, /* PC5 */ - [PC6] = {GPIOC, TIMER8, NULL, 6, 1, ADCx}, /* PC6 */ /* also TIMER3_CH1 */ - [PC7] = {GPIOC, TIMER8, NULL, 7, 2, ADCx}, /* PC7 */ /* also TIMER3_CH2 */ - [PC8] = {GPIOC, TIMER8, NULL, 8, 3, ADCx}, /* PC8 */ /* also TIMER3_CH3 */ - [PC9] = {GPIOC, TIMER8, NULL, 9, 4, ADCx}, /* PC9 */ /* also TIMER3_CH4 */ - [PC10]= {GPIOC, NULL, NULL, 10, 0, ADCx}, /* PC10 */ - [PC11]= {GPIOC, NULL, NULL, 11, 0, ADCx}, /* PC11 */ - [PC12]= {GPIOC, NULL, NULL, 12, 0, ADCx}, /* PC12 */ - - [PD2] = {GPIOD, NULL, NULL, 2, 0, ADCx}, /* PD2 */ - -# if defined(STM32_XL_DENSITY) - [PE2] = {GPIOE, TIMER3, NULL, 2, 1, ADCx}, /* PE2 */ - [PE3] = {GPIOE, TIMER3, NULL, 3, 2, ADCx}, /* PE3 */ - [PE4] = {GPIOE, TIMER3, NULL, 4, 3, ADCx}, /* PE4 */ - [PE5] = {GPIOE, TIMER3, NULL, 5, 4, ADCx}, /* PE5 */ - [PE6] = {GPIOE, NULL, NULL, 6, 0, ADCx}, /* PE6 */ - - [PF9] = {GPIOF,TIMER15, NULL, 9, 1, ADCx}, /* PF9 */ - [PF10]= {GPIOF,TIMER15, NULL, 10, 2, ADCx}, /* PF10 */ - - [PF2] = {GPIOF, NULL, ADC1, 2, 0, 10}, /* PF2 */ - - [PE7] = {GPIOE, NULL, ADC3, 7, 0, 13}, /* PE7 */ - [PE8] = {GPIOE, NULL, ADC3, 8, 0, 6}, /* PE8 */ - [PE9] = {GPIOE, TIMER1, ADC3, 9, 1, 2}, /* PE9 */ - [PE10]= {GPIOE, NULL, ADC3, 10, 0, 14}, /* PE10 */ - [PE11]= {GPIOE, TIMER1, ADC3, 11, 2, 15}, /* PE11 */ - [PE12]= {GPIOE, NULL, ADC3, 12, 0, 15}, /* PE12 */ - [PE13]= {GPIOE, TIMER1, ADC3, 13, 3, 3}, /* PE13 */ - [PE14]= {GPIOE, TIMER1, ADC4, 14, 4, 1}, /* PE14 */ - [PE15]= {GPIOE, NULL, ADC4, 15, 0, 2}, /* PE15 */ - - [PD8] = {GPIOD, NULL, ADC4, 8, 0, 12}, /* PD8 */ - [PD9] = {GPIOD, NULL, ADC4, 9, 0, 13}, /* PD0 */ - [PD10]= {GPIOD, NULL, ADC3, 10, 0, 7}, /* PD10 */ - [PD11]= {GPIOD, NULL, ADC3, 11, 0, 8}, /* PD11 */ - [PD12]= {GPIOD, TIMER4, ADC3, 12, 1, 9}, /* PD12 */ - [PD13]= {GPIOD, TIMER4, ADC3, 13, 2, 10}, /* PD13 */ - [PD14]= {GPIOD, TIMER4, ADC3, 14, 3, 11}, /* PD14 */ - [PD15]= {GPIOD, TIMER4, NULL, 15, 4, ADCx}, /* PD15 */ - - [PF6] = {GPIOF, TIMER4, NULL, 6, 4, ADCx}, /* PF6 */ - - [PD0] = {GPIOD, NULL, NULL, 0, 0, ADCx}, /* PD0 */ - [PD1] = {GPIOD, TIMER8, NULL, 1, 4, ADCx}, /* PD1 */ - - [PD3] = {GPIOD, NULL, NULL, 3, 0, ADCx}, /* PD3 */ - [PD4] = {GPIOD, TIMER2, NULL, 4, 2, ADCx}, /* PD4 */ - [PD5] = {GPIOD, NULL, NULL, 5, 0, ADCx}, /* PD5 */ - [PD6] = {GPIOD, TIMER2, NULL, 6, 4, ADCx}, /* PD6 */ - [PD7] = {GPIOD, TIMER2, NULL, 7, 3, ADCx}, /* PD7 */ - - [PE0] = {GPIOE,TIMER16, NULL, 0, 1, ADCx}, /* PE0 */ - [PE1] = {GPIOE,TIMER17, NULL, 1, 1, ADCx}, /* PE1 */ -# endif -#endif -}; - -extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { - PA0, PA1, PA2, PA3, PA4, PA6, PA7, PB0, PB1, PB10, PB11, PB14, PB15, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15, PB3, PB4, PB5, PB6, PB7, PB8, PB9, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - PC6, PC7, PC8, PC9, -# if defined(STM32_XL_DENSITY) - PE2, PE3, PE4, PE5, PF9, PF10, PE9, PE11, PE13, PE14, PD12, PD13, PD14, PD15, PF6, PD1, PD4, PD6, PD7, PE0, PE1, -# endif -#endif -}; - -extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = { - PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PB0, PB1, PB2, PB12, PB13, PB14, PB15, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - PC0, PC1, PC2, PC3, PF4, PC4, PC5, -# if defined(STM32_XL_DENSITY) - PF2, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15, PD8, PD9, PD10, PD11, PD12, PD13, PD14, -# endif -#endif -}; - -#define OSC_IN PF0 -#define OSC_OUT PF1 - -#define USB_DM PA11 -#define USB_DP PA12 - -extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { - OSC_IN, OSC_OUT, USB_DP, USB_DM,PB3, PA13, PA14 -}; diff --git a/STM32F3/variants/discovery_f3/ld/mem-flash.inc b/STM32F3/variants/discovery_f3/ld/mem-flash.inc deleted file mode 100644 index a683808..0000000 --- a/STM32F3/variants/discovery_f3/ld/mem-flash.inc +++ /dev/null @@ -1,6 +0,0 @@ -MEMORY -{ - ccm (rwx) : ORIGIN = 0x10000000, LENGTH = 8K - ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 37K - rom (rx) : ORIGIN = 0x08005000, LENGTH = 236K -} diff --git a/STM32F3/variants/discovery_f3/ld/mem-jtag.inc b/STM32F3/variants/discovery_f3/ld/mem-jtag.inc deleted file mode 100644 index 9fb4452..0000000 --- a/STM32F3/variants/discovery_f3/ld/mem-jtag.inc +++ /dev/null @@ -1,6 +0,0 @@ -MEMORY -{ - ccm (rwx) : ORIGIN = 0x10000000, LENGTH = 8K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 40K - rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K -} diff --git a/STM32F3/variants/discovery_f3/ld/mem-ram.inc b/STM32F3/variants/discovery_f3/ld/mem-ram.inc deleted file mode 100644 index 08d7608..0000000 --- a/STM32F3/variants/discovery_f3/ld/mem-ram.inc +++ /dev/null @@ -1,6 +0,0 @@ -MEMORY -{ - ccm (rwx) : ORIGIN = 0x10000000, LENGTH = 8K - ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 37K - rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K -} diff --git a/STM32F3/variants/discovery_f3/ld/vector_symbols.inc b/STM32F3/variants/discovery_f3/ld/vector_symbols.inc deleted file mode 100644 index a9d18f4..0000000 --- a/STM32F3/variants/discovery_f3/ld/vector_symbols.inc +++ /dev/null @@ -1,98 +0,0 @@ -EXTERN(__msp_init) -EXTERN(__exc_reset) -EXTERN(__exc_nmi) -EXTERN(__exc_hardfault) -EXTERN(__exc_memmanage) -EXTERN(__exc_busfault) -EXTERN(__exc_usagefault) -EXTERN(__stm32reservedexception7) -EXTERN(__stm32reservedexception8) -EXTERN(__stm32reservedexception9) -EXTERN(__stm32reservedexception10) -EXTERN(__exc_svc) -EXTERN(__exc_debug_monitor) -EXTERN(__stm32reservedexception13) -EXTERN(__exc_pendsv) -EXTERN(__exc_systick) -EXTERN(__irq_wwdg) -EXTERN(__irq_pvd) -EXTERN(__irq_tamp_stamp) -EXTERN(__irq_rtc_wkup) -EXTERN(__irq_flash) -EXTERN(__irq_rcc) -EXTERN(__irq_exti0) -EXTERN(__irq_exti1) -EXTERN(__irq_exti2) -EXTERN(__irq_exti3) -EXTERN(__irq_exti4) -EXTERN(__irq_dma1_ch1) -EXTERN(__irq_dma1_ch2) -EXTERN(__irq_dma1_ch3) -EXTERN(__irq_dma1_ch4) -EXTERN(__irq_dma1_ch5) -EXTERN(__irq_dma1_ch6) -EXTERN(__irq_dma1_ch7) -EXTERN(__irq_adc1_2) -EXTERN(__irq_usb_hp_can_tx) -EXTERN(__irq_usb_lp_can_rx0) -EXTERN(__irq_can_rx1) -EXTERN(__irq_can_sce) -EXTERN(__irq_exti9_5) -EXTERN(__irq_tim1_brk_tim15) -EXTERN(__irq_tim1_up_tim16) -EXTERN(__irq_tim1_trg_com_tim17) -EXTERN(__irq_tim1_cc) -EXTERN(__irq_tim2) -EXTERN(__irq_tim3) -EXTERN(__irq_tim4) -EXTERN(__irq_i2c1_ev) -EXTERN(__irq_i2c1_er) -EXTERN(__irq_i2c2_ev) -EXTERN(__irq_i2c2_er) -EXTERN(__irq_spi1) -EXTERN(__irq_spi2) -EXTERN(__irq_usart1) -EXTERN(__irq_usart2) -EXTERN(__irq_usart3) -EXTERN(__irq_exti15_10) -EXTERN(__irq_rtc_alarm) -EXTERN(__irq_usb_wkup) -EXTERN(__irq_tim8_brk) -EXTERN(__irq_tim8_up) -EXTERN(__irq_tim8_trg_com) -EXTERN(__irq_tim8_cc) -EXTERN(__irq_adc3) -EXTERN(__stm32reservedexception48) -EXTERN(__stm32reservedexception49) -EXTERN(__stm32reservedexception50) -EXTERN(__irq_spi3) -EXTERN(__irq_uart4) -EXTERN(__irq_uart5) -EXTERN(__irq_tim6_dacunder) -EXTERN(__irq_tim7) -EXTERN(__irq_dma2_ch1) -EXTERN(__irq_dma2_ch2) -EXTERN(__irq_dma2_ch3) -EXTERN(__irq_dma2_ch4) -EXTERN(__irq_dma2_ch5) -EXTERN(__irq_adc4) -EXTERN(__stm32reservedexception62) -EXTERN(__stm32reservedexception63) -EXTERN(__irq_comp123) -EXTERN(__irq_comp456) -EXTERN(__irq_comp7) -EXTERN(__stm32reservedexception67) -EXTERN(__stm32reservedexception68) -EXTERN(__stm32reservedexception69) -EXTERN(__stm32reservedexception70) -EXTERN(__stm32reservedexception71) -EXTERN(__stm32reservedexception72) -EXTERN(__stm32reservedexception73) -EXTERN(__irq_usb_hp) -EXTERN(__irq_usb_lp) -EXTERN(__irq_usb_wkup2) -EXTERN(__stm32reservedexception77) -EXTERN(__stm32reservedexception78) -EXTERN(__stm32reservedexception79) -EXTERN(__stm32reservedexception80) -EXTERN(__irq_fpu) diff --git a/STM32F3/variants/discovery_f3/stm32_isrs.S b/STM32F3/variants/discovery_f3/stm32_isrs.S deleted file mode 100644 index f236387..0000000 --- a/STM32F3/variants/discovery_f3/stm32_isrs.S +++ /dev/null @@ -1,331 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/* STM32F3 performance line ISR weak declarations */ - -#include - - .thumb - -/* Default handler for all non-overridden interrupts and exceptions */ - .globl __default_handler - .type __default_handler, %function - -__default_handler: - b . - - .weak __exc_nmi - .globl __exc_nmi - .set __exc_nmi, __default_handler - .weak __exc_hardfault - .globl __exc_hardfault - .set __exc_hardfault, __default_handler - .weak __exc_memmanage - .globl __exc_memmanage - .set __exc_memmanage, __default_handler - .weak __exc_busfault - .globl __exc_busfault - .set __exc_busfault, __default_handler - .weak __exc_usagefault - .globl __exc_usagefault - .set __exc_usagefault, __default_handler - .weak __stm32reservedexception7 - .globl __stm32reservedexception7 - .set __stm32reservedexception7, __default_handler - .weak __stm32reservedexception8 - .globl __stm32reservedexception8 - .set __stm32reservedexception8, __default_handler - .weak __stm32reservedexception9 - .globl __stm32reservedexception9 - .set __stm32reservedexception9, __default_handler - .weak __stm32reservedexception10 - .globl __stm32reservedexception10 - .set __stm32reservedexception10, __default_handler - .weak __exc_svc - .globl __exc_svc - .set __exc_svc, __default_handler - .weak __exc_debug_monitor - .globl __exc_debug_monitor - .set __exc_debug_monitor, __default_handler - .weak __stm32reservedexception13 - .globl __stm32reservedexception13 - .set __stm32reservedexception13, __default_handler - .weak __exc_pendsv - .globl __exc_pendsv - .set __exc_pendsv, __default_handler - .weak __exc_systick - .globl __exc_systick - .set __exc_systick, __default_handler - .weak __irq_wwdg - .globl __irq_wwdg - .set __irq_wwdg, __default_handler - .weak __irq_pvd - .globl __irq_pvd - .set __irq_pvd, __default_handler - .weak __irq_tamp_stamp - .globl __irq_tamp_stamp - .set __irq_tamp_stamp, __default_handler - .weak __irq_rtc_wkup - .globl __irq_rtc_wkup - .set __irq_rtc_wkup, __default_handler - .weak __irq_flash - .globl __irq_flash - .set __irq_flash, __default_handler - .weak __irq_rcc - .globl __irq_rcc - .set __irq_rcc, __default_handler - .weak __irq_exti0 - .globl __irq_exti0 - .set __irq_exti0, __default_handler - .weak __irq_exti1 - .globl __irq_exti1 - .set __irq_exti1, __default_handler - .weak __irq_exti2 - .globl __irq_exti2 - .set __irq_exti2, __default_handler - .weak __irq_exti3 - .globl __irq_exti3 - .set __irq_exti3, __default_handler - .weak __irq_exti4 - .globl __irq_exti4 - .set __irq_exti4, __default_handler - .weak __irq_dma1_ch1 - .globl __irq_dma1_ch1 - .set __irq_dma1_ch1, __default_handler - .weak __irq_dma1_ch2 - .globl __irq_dma1_ch2 - .set __irq_dma1_ch2, __default_handler - .weak __irq_dma1_ch3 - .globl __irq_dma1_ch3 - .set __irq_dma1_ch3, __default_handler - .weak __irq_dma1_ch4 - .globl __irq_dma1_ch4 - .set __irq_dma1_ch4, __default_handler - .weak __irq_dma1_ch5 - .globl __irq_dma1_ch5 - .set __irq_dma1_ch5, __default_handler - .weak __irq_dma1_ch6 - .globl __irq_dma1_ch6 - .set __irq_dma1_ch6, __default_handler - .weak __irq_dma1_ch7 - .globl __irq_dma1_ch7 - .set __irq_dma1_ch7, __default_handler - .weak __irq_adc1_2 - .globl __irq_adc1_2 - .set __irq_adc1_2, __default_handler - .weak __irq_usb_hp_can_tx - .globl __irq_usb_hp_can_tx - .set __irq_usb_hp_can_tx, __default_handler - .weak __irq_usb_lp_can_rx0 - .globl __irq_usb_lp_can_rx0 - .set __irq_usb_lp_can_rx0, __default_handler - .weak __irq_can_rx1 - .globl __irq_can_rx1 - .set __irq_can_rx1, __default_handler - .weak __irq_can_sce - .globl __irq_can_sce - .set __irq_can_sce, __default_handler - .weak __irq_exti9_5 - .globl __irq_exti9_5 - .set __irq_exti9_5, __default_handler - .weak __irq_tim1_brk_tim15 - .globl __irq_tim1_brk_tim15 - .set __irq_tim1_brk_tim15, __default_handler - .weak __irq_tim1_up_tim16 - .globl __irq_tim1_up_tim16 - .set __irq_tim1_up_tim16, __default_handler - .weak __irq_tim1_trg_com_tim17 - .globl __irq_tim1_trg_com_tim17 - .set __irq_tim1_trg_com_tim17, __default_handler - .weak __irq_tim1_cc - .globl __irq_tim1_cc - .set __irq_tim1_cc, __default_handler - .weak __irq_tim2 - .globl __irq_tim2 - .set __irq_tim2, __default_handler - .weak __irq_tim3 - .globl __irq_tim3 - .set __irq_tim3, __default_handler - .weak __irq_tim4 - .globl __irq_tim4 - .set __irq_tim4, __default_handler - .weak __irq_i2c1_ev - .globl __irq_i2c1_ev - .set __irq_i2c1_ev, __default_handler - .weak __irq_i2c1_er - .globl __irq_i2c1_er - .set __irq_i2c1_er, __default_handler - .weak __irq_i2c2_ev - .globl __irq_i2c2_ev - .set __irq_i2c2_ev, __default_handler - .weak __irq_i2c2_er - .globl __irq_i2c2_er - .set __irq_i2c2_er, __default_handler - .weak __irq_spi1 - .globl __irq_spi1 - .set __irq_spi1, __default_handler - .weak __irq_spi2 - .globl __irq_spi2 - .set __irq_spi2, __default_handler - .weak __irq_usart1 - .globl __irq_usart1 - .set __irq_usart1, __default_handler - .weak __irq_usart2 - .globl __irq_usart2 - .set __irq_usart2, __default_handler - .weak __irq_usart3 - .globl __irq_usart3 - .set __irq_usart3, __default_handler - .weak __irq_exti15_10 - .globl __irq_exti15_10 - .set __irq_exti15_10, __default_handler - .weak __irq_rtc_alarm - .globl __irq_rtc_alarm - .set __irq_rtc_alarm, __default_handler - .weak __irq_usb_wkup - .globl __irq_usb_wkup - .set __irq_usb_wkup, __default_handler - - .weak __irq_tim8_brk - .globl __irq_tim8_brk - .set __irq_tim8_brk, __default_handler - .weak __irq_tim8_up - .globl __irq_tim8_up - .set __irq_tim8_up, __default_handler - .weak __irq_tim8_trg_com - .globl __irq_tim8_trg_com - .set __irq_tim8_trg_com, __default_handler - .weak __irq_tim8_cc - .globl __irq_tim8_cc - .set __irq_tim8_cc, __default_handler - .weak __irq_adc3 - .globl __irq_adc3 - .set __irq_adc3, __default_handler - .weak __stm32reservedexception48 - .globl __stm32reservedexception48 - .set __stm32reservedexception48, __default_handler - .weak __stm32reservedexception49 - .globl __stm32reservedexception49 - .set __stm32reservedexception49, __default_handler - .weak __stm32reservedexception50 - .globl __stm32reservedexception50 - .set __stm32reservedexception50, __default_handler - .weak __irq_spi3 - .globl __irq_spi3 - .set __irq_spi3, __default_handler - .weak __irq_uart4 - .globl __irq_uart4 - .set __irq_uart4, __default_handler - .weak __irq_uart5 - .globl __irq_uart5 - .set __irq_uart5, __default_handler - .weak __irq_tim6_dacunder - .globl __irq_tim6_dacunder - .set __irq_tim6_dac, __default_handler - .weak __irq_tim7 - .globl __irq_tim7 - .set __irq_tim7, __default_handler - .weak __irq_dma2_ch1 - .globl __irq_dma2_ch1 - .set __irq_dma2_ch1, __default_handler - .weak __irq_dma2_ch2 - .globl __irq_dma2_ch2 - .set __irq_dma2_ch2, __default_handler - .weak __irq_dma2_ch3 - .globl __irq_dma2_ch3 - .set __irq_dma2_ch3, __default_handler - .weak __irq_dma2_ch4 - .globl __irq_dma2_ch4 - .set __irq_dma2_ch4, __default_handler - .weak __irq_dma2_ch5 - .globl __irq_dma2_ch5 - .set __irq_dma2_ch5, __default_handler - .weak __irq_adc4 - .globl __irq_adc4 - .set __irq_adc4, __default_handler - .weak __stm32reservedexception62 - .globl __stm32reservedexception62 - .set __stm32reservedexception62, __default_handler - .weak __stm32reservedexception63 - .globl __stm32reservedexception63 - .set __stm32reservedexception63, __default_handler - .weak __irq_comp123 - .globl __irq_comp123 - .set __irq_comp123, __default_handler - .weak __irq_comp456 - .globl __irq_comp456 - .set __irq_comp456, __default_handler - .weak __irq_comp7 - .globl __irq_comp7 - .set __irq_comp7, __default_handler - .weak __stm32reservedexception67 - .globl __stm32reservedexception67 - .set __stm32reservedexception67, __default_handler - .weak __stm32reservedexception68 - .globl __stm32reservedexception68 - .set __stm32reservedexception68, __default_handler - .weak __stm32reservedexception69 - .globl __stm32reservedexception69 - .set __stm32reservedexception69, __default_handler - .weak __stm32reservedexception70 - .globl __stm32reservedexception70 - .set __stm32reservedexception70, __default_handler - .weak __stm32reservedexception71 - .globl __stm32reservedexception71 - .set __stm32reservedexception71, __default_handler - .weak __stm32reservedexception72 - .globl __stm32reservedexception72 - .set __stm32reservedexception72, __default_handler - .weak __stm32reservedexception73 - .globl __stm32reservedexception73 - .set __stm32reservedexception73, __default_handler - .weak __irq_usb_hp - .globl __irq_usb_hp - .set __irq_usb_hp, __default_handler - .weak __irq_usb_lp - .globl __irq_usb_lp - .set __irq_usb_lp, __default_handler - .weak __irq_usb_wkup2 - .globl __irq_usb_wkup2 - .set __irq_usb_wkup2, __default_handler - .weak __stm32reservedexception77 - .globl __stm32reservedexception77 - .set __stm32reservedexception77, __default_handler - .weak __stm32reservedexception78 - .globl __stm32reservedexception78 - .set __stm32reservedexception78, __default_handler - .weak __stm32reservedexception79 - .globl __stm32reservedexception79 - .set __stm32reservedexception79, __default_handler - .weak __stm32reservedexception80 - .globl __stm32reservedexception80 - .set __stm32reservedexception80, __default_handler - .weak __irq_fpu - .globl __irq_fpu - .set __irq_fpu, __default_handler - .weak __reserved - .globl __reserved - .set __reserved, __default_handler diff --git a/STM32F3/variants/discovery_f3/stm32_vector_table.S b/STM32F3/variants/discovery_f3/stm32_vector_table.S deleted file mode 100644 index f68fa4b..0000000 --- a/STM32F3/variants/discovery_f3/stm32_vector_table.S +++ /dev/null @@ -1,134 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ /* STM32F3 performance line vector table */ #include - .section ".stm32.interrupt_vector" - - .globl __stm32_vector_table - .type __stm32_vector_table, %object - -__stm32_vector_table: -/* CM4 core interrupts */ - .long __msp_init - .long __exc_reset - .long __exc_nmi - .long __exc_hardfault - .long __exc_memmanage - .long __exc_busfault - .long __exc_usagefault - .long __stm32reservedexception7 - .long __stm32reservedexception8 - .long __stm32reservedexception9 - .long __stm32reservedexception10 - .long __exc_svc - .long __exc_debug_monitor - .long __stm32reservedexception13 - .long __exc_pendsv - .long __exc_systick -/* Peripheral interrupts */ - .long __irq_wwdg - .long __irq_pvd - .long __irq_tamp_stamp - .long __irq_rtc_wkup - .long __irq_flash - .long __irq_rcc - .long __irq_exti0 - .long __irq_exti1 - .long __irq_exti2 - .long __irq_exti3 - .long __irq_exti4 - .long __irq_dma1_ch1 - .long __irq_dma1_ch2 - .long __irq_dma1_ch3 - .long __irq_dma1_ch4 - .long __irq_dma1_ch5 - .long __irq_dma1_ch6 - .long __irq_dma1_ch7 - .long __irq_adc1_2 - .long __irq_usb_hp_can_tx - .long __irq_usb_lp_can_rx0 - .long __irq_can_rx1 - .long __irq_can_sce - .long __irq_exti9_5 - .long __irq_tim1_brk_tim15 - .long __irq_tim1_up_tim16 - .long __irq_tim1_trg_com_tim17 - .long __irq_tim1_cc - .long __irq_tim2 - .long __irq_tim3 - .long __irq_tim4 - .long __irq_i2c1_ev - .long __irq_i2c1_er - .long __irq_i2c2_ev - .long __irq_i2c2_er - .long __irq_spi1 - .long __irq_spi2 - .long __irq_usart1 - .long __irq_usart2 - .long __irq_usart3 - .long __irq_exti15_10 - .long __irq_rtc_alarm - .long __irq_usb_wkup - - .long __irq_tim8_brk - .long __irq_tim8_up - .long __irq_tim8_trg_com - .long __irq_tim8_cc - .long __irq_adc3 - .long __stm32reservedexception48 - .long __stm32reservedexception49 - .long __stm32reservedexception50 - .long __irq_spi3 - .long __irq_uart4 - .long __irq_uart5 - .long __irq_tim6_dacunder - .long __irq_tim7 - .long __irq_dma2_ch1 - .long __irq_dma2_ch2 - .long __irq_dma2_ch3 - .long __irq_dma2_ch4 - .long __irq_dma2_ch5 - .long __irq_adc4 - .long __stm32reservedexception62 - .long __stm32reservedexception63 - .long __irq_comp123 - .long __irq_comp456 - .long __irq_comp7 - .long __stm32reservedexception67 - .long __stm32reservedexception68 - .long __stm32reservedexception69 - .long __stm32reservedexception70 - .long __stm32reservedexception71 - .long __stm32reservedexception72 - .long __stm32reservedexception73 - .long __irq_usb_hp - .long __irq_usb_lp - .long __irq_usb_wkup2 - .long __stm32reservedexception77 - .long __stm32reservedexception78 - .long __stm32reservedexception79 - .long __stm32reservedexception80 - .long __irq_fpu - - .size __stm32_vector_table, . - __stm32_vector_table diff --git a/STM32F4/boards.txt b/STM32F4/boards.txt index 7577d19..907e6f7 100644 --- a/STM32F4/boards.txt +++ b/STM32F4/boards.txt @@ -1,5 +1,9 @@ # +menu.usb_cfg=USB configuration +menu.opt=Optimize +menu.upload_method=Upload method + ############################################################## discovery_f407.name=STM32 Discovery F407 @@ -8,9 +12,8 @@ discovery_f407.upload.protocol=stlink #discovery_f407.upload.use_1200bps_touch=false discovery_f407.upload.file_type=bin -discovery_f407.upload.ram.maximum_size=17000 -discovery_f407.upload.flash.maximum_size=1048576 discovery_f407.upload.maximum_size=1048576 +discovery_f407.upload.maximum_data_size=131072 #discovery_f407.upload.usbID=1EAF:0003 #discovery_f407.upload.altID=1 @@ -28,7 +31,128 @@ discovery_f407.build.density=STM32_HIGH_DENSITY discovery_f407.build.error_led_port=GPIOD discovery_f407.build.error_led_pin=14 discovery_f407.build.board=STM32DiscoveryF407 +discovery_f407.build.vect_flags=-DVECT_TAB_FLASH -DUSER_ADDR_ROM=(uint32)0x08000000 +discovery_f407.menu.usb_cfg.usb_nc=USB inactive +discovery_f407.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC +discovery_f407.menu.usb_cfg.usb_serial=USB serial (CDC) +discovery_f407.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB +discovery_f407.menu.usb_cfg.usb_msc=USB Mass Storage (MSC) +discovery_f407.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC + +#-- Optimizations +discovery_f407.menu.opt.osstd=Smallest (default) +discovery_f407.menu.opt.osstd.build.flags.optimize=-Os +discovery_f407.menu.opt.osstd.build.flags.ldspecs= +discovery_f407.menu.opt.oslto=Smallest Code with LTO +discovery_f407.menu.opt.oslto.build.flags.optimize=-Os -flto +discovery_f407.menu.opt.oslto.build.flags.ldspecs=-flto +discovery_f407.menu.opt.o1std=Fast (-O1) +discovery_f407.menu.opt.o1std.build.flags.optimize=-O1 +discovery_f407.menu.opt.o1std.build.flags.ldspecs= +discovery_f407.menu.opt.o1lto=Fast (-O1) with LTO +discovery_f407.menu.opt.o1lto.build.flags.optimize=-O1 -flto +discovery_f407.menu.opt.o1lto.build.flags.ldspecs=-flto +discovery_f407.menu.opt.o2std=Faster (-O2) +discovery_f407.menu.opt.o2std.build.flags.optimize=-O2 +discovery_f407.menu.opt.o2std.build.flags.ldspecs= +discovery_f407.menu.opt.o2lto=Faster (-O2) with LTO +discovery_f407.menu.opt.o2lto.build.flags.optimize=-O2 -flto +discovery_f407.menu.opt.o2lto.build.flags.ldspecs=-flto +discovery_f407.menu.opt.o3std=Fastest (-O3) +discovery_f407.menu.opt.o3std.build.flags.optimize=-O3 +discovery_f407.menu.opt.o3std.build.flags.ldspecs= +discovery_f407.menu.opt.o3lto=Fastest (-O3) with LTO +discovery_f407.menu.opt.o3lto.build.flags.optimize=-O3 -flto +discovery_f407.menu.opt.o3lto.build.flags.ldspecs=-flto +discovery_f407.menu.opt.ogstd=Debug (-g) +discovery_f407.menu.opt.ogstd.build.flags.optimize=-Og +discovery_f407.menu.opt.ogstd.build.flags.ldspecs= +############################################################## +generic_f407v.name=Generic STM32F407V series + +generic_f407v.upload.tool=stlink_upload +generic_f407v.upload.protocol=stlink + +generic_f407v.upload.file_type=bin +generic_f407v.upload.maximum_size=514288 +generic_f407v.upload.maximum_data_size=131072 + +#generic_f407v.upload.usbID=0483:3748 +#generic_f407v.upload.altID=1 +#generic_f407v.upload.auto_reset=true + +generic_f407v.build.mcu=cortex-m4 +generic_f407v.build.f_cpu=168000000L +generic_f407v.build.core=maple +generic_f407v.build.extra_flags=-mthumb -DSTM32_HIGH_DENSITY -DSTM32F4 -DBOARD_generic_f407v +generic_f407v.build.ldscript=ld/jtag.ld +generic_f407v.build.variant=generic_f407v +generic_f407v.build.variant_system_lib=lib_f407.a +generic_f407v.build.vect=VECT_TAB_BASE +generic_f407v.build.density=STM32_HIGH_DENSITY +generic_f407v.build.error_led_port=GPIOA +generic_f407v.build.error_led_pin=7 +generic_f407v.build.board=STM32GenericF407VET6 +generic_f407v.build.vect_flags=-DVECT_TAB_FLASH -DUSER_ADDR_ROM=(uint32)0x08000000 + +generic_f407v.menu.usb_cfg.usb_nc=USB inactive +generic_f407v.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC + +generic_f407v.menu.usb_cfg.usb_serial=USB serial (CDC) +generic_f407v.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB +generic_f407v.menu.usb_cfg.usb_msc=USB Mass Storage (MSC) +generic_f407v.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC + +#note STLink is the default from the main block of config above, so does not need settings for everything +generic_f407v.menu.upload_method.STLinkMethod=STLink +generic_f407v.menu.upload_method.STLinkMethod.upload.protocol=STLink +generic_f407v.menu.upload_method.STLinkMethod.upload.tool=stlink_upload +generic_f407v.menu.upload_method.STLinkMethod.upload.dfuse_addr=0x08004000 +generic_f407v.menu.upload_method.STLinkMethod.build.vect_flags=-DVECT_TAB_FLASH -DUSER_ADDR_ROM=(uint32)0x08000000 + + +generic_f407v.menu.upload_method.DFUUploadMethod=STM32duino bootloader +generic_f407v.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu +generic_f407v.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload +generic_f407v.menu.upload_method.DFUUploadMethod.build.vect_flags=-DVECT_TAB_FLASH -DUSER_ADDR_ROM=(uint32)0x08004000 +generic_f407v.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_8004000.ld +generic_f407v.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 +generic_f407v.menu.upload_method.DFUUploadMethod.upload.altID=2 + + + + + + +#-- Optimizations +generic_f407v.menu.opt.osstd=Smallest (default) +generic_f407v.menu.opt.osstd.build.flags.optimize=-Os +generic_f407v.menu.opt.osstd.build.flags.ldspecs= +generic_f407v.menu.opt.oslto=Smallest Code with LTO +generic_f407v.menu.opt.oslto.build.flags.optimize=-Os -flto +generic_f407v.menu.opt.oslto.build.flags.ldspecs=-flto +generic_f407v.menu.opt.o1std=Fast (-O1) +generic_f407v.menu.opt.o1std.build.flags.optimize=-O1 +generic_f407v.menu.opt.o1std.build.flags.ldspecs= +generic_f407v.menu.opt.o1lto=Fast (-O1) with LTO +generic_f407v.menu.opt.o1lto.build.flags.optimize=-O1 -flto +generic_f407v.menu.opt.o1lto.build.flags.ldspecs=-flto +generic_f407v.menu.opt.o2std=Faster (-O2) +generic_f407v.menu.opt.o2std.build.flags.optimize=-O2 +generic_f407v.menu.opt.o2std.build.flags.ldspecs= +generic_f407v.menu.opt.o2lto=Faster (-O2) with LTO +generic_f407v.menu.opt.o2lto.build.flags.optimize=-O2 -flto +generic_f407v.menu.opt.o2lto.build.flags.ldspecs=-flto +generic_f407v.menu.opt.o3std=Fastest (-O3) +generic_f407v.menu.opt.o3std.build.flags.optimize=-O3 +generic_f407v.menu.opt.o3std.build.flags.ldspecs= +generic_f407v.menu.opt.o3lto=Fastest (-O3) with LTO +generic_f407v.menu.opt.o3lto.build.flags.optimize=-O3 -flto +generic_f407v.menu.opt.o3lto.build.flags.ldspecs=-flto +generic_f407v.menu.opt.ogstd=Debug (-g) +generic_f407v.menu.opt.ogstd.build.flags.optimize=-Og +generic_f407v.menu.opt.ogstd.build.flags.ldspecs= ############################################################## stm32f4stamp.name=STM32F4Stamp F405 @@ -37,9 +161,8 @@ stm32f4stamp.upload.protocol=maple_dfu #stm32f4stamp.upload.use_1200bps_touch=false stm32f4stamp.upload.file_type=bin -stm32f4stamp.upload.ram.maximum_size=196608 -stm32f4stamp.upload.flash.maximum_size=1048576 stm32f4stamp.upload.maximum_size=1048576 +stm32f4stamp.upload.maximum_data_size=131072 stm32f4stamp.upload.usbID=0483:df11 stm32f4stamp.upload.altID=0 @@ -49,7 +172,7 @@ stm32f4stamp.upload.dfuse_addr=0x8000000 stm32f4stamp.build.mcu=cortex-m4 stm32f4stamp.build.f_cpu=168000000L stm32f4stamp.build.core=maple -stm32f4stamp.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F2 -DSTM32F4 -DBOARD_discovery_f4 +stm32f4stamp.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F4 -DBOARD_discovery_f4 stm32f4stamp.build.ldscript=ld/jtag.ld stm32f4stamp.build.variant=discovery_f407 stm32f4stamp.build.variant_system_lib=lib_f407.a @@ -58,7 +181,43 @@ stm32f4stamp.build.density=STM32_HIGH_DENSITY stm32f4stamp.build.error_led_port=GPIOD stm32f4stamp.build.error_led_pin=14 stm32f4stamp.build.board=STM32F4StampF405 +stm32f4stamp.build.vect_flags=-DVECT_TAB_FLASH -DUSER_ADDR_ROM=(uint32)0x08000000 +stm32f4stamp.menu.usb_cfg.usb_nc=USB inactive +stm32f4stamp.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC +stm32f4stamp.menu.usb_cfg.usb_serial=USB serial (CDC) +stm32f4stamp.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB +stm32f4stamp.menu.usb_cfg.usb_msc=USB Mass Storage (MSC) +stm32f4stamp.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC + +#-- Optimizations +stm32f4stamp.menu.opt.osstd=Smallest (default) +stm32f4stamp.menu.opt.osstd.build.flags.optimize=-Os +stm32f4stamp.menu.opt.osstd.build.flags.ldspecs= +stm32f4stamp.menu.opt.oslto=Smallest Code with LTO +stm32f4stamp.menu.opt.oslto.build.flags.optimize=-Os -flto +stm32f4stamp.menu.opt.oslto.build.flags.ldspecs=-flto +stm32f4stamp.menu.opt.o1std=Fast (-O1) +stm32f4stamp.menu.opt.o1std.build.flags.optimize=-O1 +stm32f4stamp.menu.opt.o1std.build.flags.ldspecs= +stm32f4stamp.menu.opt.o1lto=Fast (-O1) with LTO +stm32f4stamp.menu.opt.o1lto.build.flags.optimize=-O1 -flto +stm32f4stamp.menu.opt.o1lto.build.flags.ldspecs=-flto +stm32f4stamp.menu.opt.o2std=Faster (-O2) +stm32f4stamp.menu.opt.o2std.build.flags.optimize=-O2 +stm32f4stamp.menu.opt.o2std.build.flags.ldspecs= +stm32f4stamp.menu.opt.o2lto=Faster (-O2) with LTO +stm32f4stamp.menu.opt.o2lto.build.flags.optimize=-O2 -flto +stm32f4stamp.menu.opt.o2lto.build.flags.ldspecs=-flto +stm32f4stamp.menu.opt.o3std=Fastest (-O3) +stm32f4stamp.menu.opt.o3std.build.flags.optimize=-O3 +stm32f4stamp.menu.opt.o3std.build.flags.ldspecs= +stm32f4stamp.menu.opt.o3lto=Fastest (-O3) with LTO +stm32f4stamp.menu.opt.o3lto.build.flags.optimize=-O3 -flto +stm32f4stamp.menu.opt.o3lto.build.flags.ldspecs=-flto +stm32f4stamp.menu.opt.ogstd=Debug (-g) +stm32f4stamp.menu.opt.ogstd.build.flags.optimize=-Og +stm32f4stamp.menu.opt.ogstd.build.flags.ldspecs= ############################################################## netduino2plus.name=Netduino2 F405 @@ -67,9 +226,8 @@ netduino2plus.upload.protocol=maple_dfu #netduino2plus.upload.use_1200bps_touch=false netduino2plus.upload.file_type=bin -netduino2plus.upload.ram.maximum_size=196608 -netduino2plus.upload.flash.maximum_size=1048576 netduino2plus.upload.maximum_size=1048576 +netduino2plus.upload.maximum_data_size=131072 netduino2plus.upload.usbID=0483:df11 netduino2plus.upload.altID=0 @@ -79,7 +237,7 @@ netduino2plus.upload.dfuse_addr=0x8000000 netduino2plus.build.mcu=cortex-m4 netduino2plus.build.f_cpu=168000000L netduino2plus.build.core=maple -netduino2plus.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F2 -DSTM32F4 -DBOARD_discovery_f4 -DARDUINO_STM32F4_NETDUINO2PLUS +netduino2plus.build.extra_flags=-DMCU_STM32F406VG -mthumb -DSTM32_HIGH_DENSITY -DSTM32F4 -DBOARD_discovery_f4 -DARDUINO_STM32F4_NETDUINO2PLUS netduino2plus.build.ldscript=ld/jtag.ld netduino2plus.build.variant=discovery_f407 netduino2plus.build.variant_system_lib=lib_f407.a @@ -89,5 +247,40 @@ netduino2plus.build.error_led_port=GPIOD netduino2plus.build.error_led_pin=14 netduino2plus.build.board=Netduino2F405 +netduino2plus.menu.usb_cfg.usb_nc=USB inactive +netduino2plus.menu.usb_cfg.usb_nc.build.cpu_flags=-DUSB_NC +netduino2plus.menu.usb_cfg.usb_serial=USB serial (CDC) +netduino2plus.menu.usb_cfg.usb_serial.build.cpu_flags=-DSERIAL_USB +netduino2plus.menu.usb_cfg.usb_msc=USB Mass Storage (MSC) +netduino2plus.menu.usb_cfg.usb_msc.build.cpu_flags=-DUSB_MSC + +#-- Optimizations +netduino2plus.menu.opt.osstd=Smallest (default) +netduino2plus.menu.opt.osstd.build.flags.optimize=-Os +netduino2plus.menu.opt.osstd.build.flags.ldspecs= +netduino2plus.menu.opt.oslto=Smallest Code with LTO +netduino2plus.menu.opt.oslto.build.flags.optimize=-Os -flto +netduino2plus.menu.opt.oslto.build.flags.ldspecs=-flto +netduino2plus.menu.opt.o1std=Fast (-O1) +netduino2plus.menu.opt.o1std.build.flags.optimize=-O1 +netduino2plus.menu.opt.o1std.build.flags.ldspecs= +netduino2plus.menu.opt.o1lto=Fast (-O1) with LTO +netduino2plus.menu.opt.o1lto.build.flags.optimize=-O1 -flto +netduino2plus.menu.opt.o1lto.build.flags.ldspecs=-flto +netduino2plus.menu.opt.o2std=Faster (-O2) +netduino2plus.menu.opt.o2std.build.flags.optimize=-O2 +netduino2plus.menu.opt.o2std.build.flags.ldspecs= +netduino2plus.menu.opt.o2lto=Faster (-O2) with LTO +netduino2plus.menu.opt.o2lto.build.flags.optimize=-O2 -flto +netduino2plus.menu.opt.o2lto.build.flags.ldspecs=-flto +netduino2plus.menu.opt.o3std=Fastest (-O3) +netduino2plus.menu.opt.o3std.build.flags.optimize=-O3 +netduino2plus.menu.opt.o3std.build.flags.ldspecs= +netduino2plus.menu.opt.o3lto=Fastest (-O3) with LTO +netduino2plus.menu.opt.o3lto.build.flags.optimize=-O3 -flto +netduino2plus.menu.opt.o3lto.build.flags.ldspecs=-flto +netduino2plus.menu.opt.ogstd=Debug (-g) +netduino2plus.menu.opt.ogstd.build.flags.optimize=-Og +netduino2plus.menu.opt.ogstd.build.flags.ldspecs= ############################################################## diff --git a/STM32F4/cores/maple/Arduino.h b/STM32F4/cores/maple/Arduino.h deleted file mode 100644 index d02a50c..0000000 --- a/STM32F4/cores/maple/Arduino.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef Arduino_h -#define Arduino_h -#include "WProgram.h" -#endif - -#include "variant.h" diff --git a/STM32F4/cores/maple/Client.h b/STM32F4/cores/maple/Client.h index b8e5d93..57bedb8 100644 --- a/STM32F4/cores/maple/Client.h +++ b/STM32F4/cores/maple/Client.h @@ -17,8 +17,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef client_h -#define client_h +#ifndef _CLIENT_H_ +#define _CLIENT_H_ + #include "Print.h" #include "Stream.h" #include "IPAddress.h" diff --git a/STM32F4/cores/maple/HardwareTimer.h b/STM32F4/cores/maple/HardwareTimer.h index 89e3564..c90356b 100644 --- a/STM32F4/cores/maple/HardwareTimer.h +++ b/STM32F4/cores/maple/HardwareTimer.h @@ -33,7 +33,7 @@ // TODO [0.1.0] Remove deprecated pieces, pick a better API -#include "timer.h" +#include /** Timer mode. */ typedef timer_mode TimerMode; diff --git a/STM32F4/cores/maple/IPAddress.h b/STM32F4/cores/maple/IPAddress.h index 271b240..c6e0697 100644 --- a/STM32F4/cores/maple/IPAddress.h +++ b/STM32F4/cores/maple/IPAddress.h @@ -17,8 +17,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef IPAddress_h -#define IPAddress_h +#ifndef _IPAddress_h_ +#define _IPAddress_h_ #include #include diff --git a/STM32F4/cores/maple/Print.cpp b/STM32F4/cores/maple/Print.cpp index 76f386b..2e6e154 100644 --- a/STM32F4/cores/maple/Print.cpp +++ b/STM32F4/cores/maple/Print.cpp @@ -47,12 +47,8 @@ */ size_t Print::write(const char *str) { - size_t n = 0; - while (*str) { - write(*str++); - n++; - } - return n; + if (str == NULL) return 0; + return write((const uint8_t *)str, strlen(str)); } size_t Print::write(const void *buffer, uint32 size) { @@ -99,10 +95,6 @@ size_t Print::print(unsigned long n, int base) { } size_t Print::print(long long n, int base) { - if (base == BYTE) - { - return write((uint8)n); - } if (n < 0) { print('-'); n = -n; @@ -111,13 +103,7 @@ size_t Print::print(long long n, int base) { } size_t Print::print(unsigned long long n, int base) { -size_t c=0; - if (base == BYTE) { - c= write((uint8)n); - } else { - c= printNumber(n, base); - } - return c; + return printNumber(n, base); } size_t Print::print(double n, int digits) { diff --git a/STM32F4/cores/maple/Print.h b/STM32F4/cores/maple/Print.h index bd37385..f265fac 100644 --- a/STM32F4/cores/maple/Print.h +++ b/STM32F4/cores/maple/Print.h @@ -28,7 +28,6 @@ #include "Printable.h" enum { - BYTE = 0, BIN = 2, OCT = 8, DEC = 10, diff --git a/STM32F4/cores/maple/Server.h b/STM32F4/cores/maple/Server.h index 69e3e39..4a95c9f 100644 --- a/STM32F4/cores/maple/Server.h +++ b/STM32F4/cores/maple/Server.h @@ -17,8 +17,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef server_h -#define server_h +#ifndef _SERVER_H_ +#define _SERVER_H_ #include "Print.h" diff --git a/STM32F4/cores/maple/Stream.h b/STM32F4/cores/maple/Stream.h index abdcd17..870fbf0 100644 --- a/STM32F4/cores/maple/Stream.h +++ b/STM32F4/cores/maple/Stream.h @@ -19,8 +19,8 @@ parsing functions based on TextFinder library by Michael Margolis */ -#ifndef Stream_h -#define Stream_h +#ifndef _STREAM_H_ +#define _STREAM_H_ #include #include "Print.h" diff --git a/STM32F4/cores/maple/Udp.h b/STM32F4/cores/maple/Udp.h index dc5644b..1652caf 100644 --- a/STM32F4/cores/maple/Udp.h +++ b/STM32F4/cores/maple/Udp.h @@ -32,8 +32,8 @@ * bjoern@cs.stanford.edu 12/30/2008 */ -#ifndef udp_h -#define udp_h +#ifndef _UDP_H_ +#define _UDP_H_ #include #include diff --git a/STM32F4/cores/maple/WProgram.h b/STM32F4/cores/maple/WProgram.h index 2949a0a..82b759a 100644 --- a/STM32F4/cores/maple/WProgram.h +++ b/STM32F4/cores/maple/WProgram.h @@ -24,7 +24,12 @@ * SOFTWARE. *****************************************************************************/ -#include "wirish.h" +#ifndef _WPROGRAM_H_ +#define _WPROGRAM_H_ + +#include void setup(); void loop(); + +#endif \ No newline at end of file diff --git a/STM32F4/cores/maple/WString.h b/STM32F4/cores/maple/WString.h index 9038578..ec0eae7 100644 --- a/STM32F4/cores/maple/WString.h +++ b/STM32F4/cores/maple/WString.h @@ -19,8 +19,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef String_class_h -#define String_class_h +#ifndef _WSTRING_H_ +#define _WSTRING_H_ + #ifdef __cplusplus #include @@ -225,4 +226,4 @@ public: }; #endif // __cplusplus -#endif // String_class_h +#endif // _WSTRING_H_ diff --git a/STM32F4/cores/maple/bits.h b/STM32F4/cores/maple/bits.h index 3e755b7..3e3eff1 100644 --- a/STM32F4/cores/maple/bits.h +++ b/STM32F4/cores/maple/bits.h @@ -27,4 +27,9 @@ /* Note: Use of this header file is deprecated. Use bit_constants.h instead. */ +#ifndef _BITS_H_ +#define _BITS_H_ + #include "bit_constants.h" + +#endif diff --git a/STM32F4/cores/maple/boards.cpp b/STM32F4/cores/maple/boards.cpp index a856571..4b0480f 100644 --- a/STM32F4/cores/maple/boards.cpp +++ b/STM32F4/cores/maple/boards.cpp @@ -33,17 +33,16 @@ */ #include "boards.h" -#include "flash.h" -#include "rcc.h" -#include "nvic.h" -#include "systick.h" -#include "gpio.h" -#include "adc.h" -#include "timer.h" +#include +#include +#include +#include +#include +#include +#include #include "usb.h" -#ifdef STM32F2 -//#include "usbF4.h" -#endif +#include "usb_serial.h" + static void setupFlash(void); static void setupClocks(void); @@ -59,7 +58,7 @@ void init(void) { systick_init(SYSTICK_RELOAD_VAL); gpio_init_all(); -#ifdef STM32F2 +#ifdef STM32F4 rcc_clk_enable(RCC_SYSCFG); #else afio_init(); @@ -69,7 +68,9 @@ void init(void) { setupADC(); setupTimers(); - //setupUSB(); +#ifdef SERIAL_USB + SerialUSB.begin(); // includes { setupUSB(); } +#endif } /* You could farm this out to the files in boards/ if e.g. it takes @@ -84,11 +85,13 @@ bool boardUsesPin(uint8 pin) { } static void setupFlash(void) { +/* #ifndef STM32F2 // for F2 and F4 CPUs this is done in SetupClock...(), e.g. in SetupClock168MHz() flash_enable_prefetch(); flash_set_latency(FLASH_WAIT_STATE_2); #endif +*/ } /* @@ -121,8 +124,8 @@ static void setupNVIC() { static void adcDefaultConfig(const adc_dev* dev); static void setupADC() { -#ifdef STM32F2 - setupADC_F2(); +#ifdef STM32F4 + setupADC_F4(); #else rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6); #endif diff --git a/STM32F4/cores/maple/boards.h b/STM32F4/cores/maple/boards.h index 00d07cd..d37bff4 100644 --- a/STM32F4/cores/maple/boards.h +++ b/STM32F4/cores/maple/boards.h @@ -39,11 +39,8 @@ #ifndef _BOARDS_H_ #define _BOARDS_H_ -#include "libmaple.h" -#include "gpio.h" -#include "timer.h" - -#include "wirish_types.h" +#include +#include /* Set of all possible pin names; not all boards have all these (note * that we use the Dx convention since all of the Maple's pins are @@ -55,9 +52,12 @@ enum { D32, D33, D34, D35, D36, D37, D38, D39, D40, D41, D42, D43, D44, D45, D46, D47, D48, D49, D50, D51, D52, D53, D54, D55, D56, D57, D58, D59, D60, D61, D62, D63, D64, D65, D66, D67, D68, D69, D70, D71, D72, D73, D74, D75, D76, +#if 0 // not available on LQFP100 package D77, D78, D79, D80, D81, D82, D83, D84, D85, D86, D87, D88, D89, D90, D91, D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105, - D106, D107, D108, D109, D110, D111, }; + D106, D107, D108, D109, D110, D111, +#endif // not available on LQFP100 package +}; /** * @brief Maps each Maple pin to a corresponding stm32_pin_info. @@ -115,31 +115,20 @@ extern void boardInit(void); * @return true if the given pin is in boardUsedPins, and false otherwise. * @see boardUsedPins */ -bool boardUsesPin(uint8 pin); +extern bool boardUsesPin(uint8 pin); /* Include the appropriate private header from boards/: */ /* FIXME HACK put boards/ before these paths once IDE uses make. */ -#ifdef BOARD_maple -#include "maple.h" -#elif defined(BOARD_maple_native) -#include "maple_native.h" -#elif defined(BOARD_maple_mini) -#include "maple_mini.h" -#elif defined(BOARD_maple_RET6) -/* - * **NOT** MAPLE REV6. This the **Maple RET6 EDITION**, which is a - * Maple with an STM32F103RET6 (...RET6) instead of an STM32F103RBT6 - * (...RBT6) on it. Maple Rev6 (as of March 2011) DOES NOT EXIST. - */ -#include "maple_RET6.h" -#elif defined(BOARD_aeroquad32) || defined(BOARD_aeroquad32f1) +#if defined(BOARD_aeroquad32) || defined(BOARD_aeroquad32f1) #include "aeroquad32.h" #elif defined(BOARD_aeroquad32mini) #include "aeroquad32mini.h" #elif defined(BOARD_discovery_f4) #include "discovery_f4.h" +#elif defined(BOARD_generic_f407v) +#include "generic_f407v.h" #elif defined(BOARD_freeflight) #include "freeflight.h" #else @@ -160,4 +149,12 @@ bool boardUsesPin(uint8 pin); #define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND #define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL) +#ifndef SYSTICK_RELOAD_VAL +#define SYSTICK_RELOAD_VAL (1000 * CYCLES_PER_MICROSECOND - 1) +#endif + +#ifndef BOARD_BUTTON_PRESSED_LEVEL +#define BOARD_BUTTON_PRESSED_LEVEL HIGH +#endif + #endif diff --git a/STM32F4/cores/maple/ext_interrupts.cpp b/STM32F4/cores/maple/ext_interrupts.cpp index f014f13..7111d0c 100644 --- a/STM32F4/cores/maple/ext_interrupts.cpp +++ b/STM32F4/cores/maple/ext_interrupts.cpp @@ -31,8 +31,8 @@ */ #include "boards.h" -#include "gpio.h" -#include "exti.h" +#include +#include #include "ext_interrupts.h" static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode); @@ -51,7 +51,7 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) { exti_trigger_mode outMode = exti_out_mode(mode); - exti_attach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit), + exti_attach_interrupt((afio_exti_num)(pin&0x0F), gpio_exti_port(PIN_MAP[pin].gpio_device), handler, outMode); @@ -66,7 +66,7 @@ void detachInterrupt(uint8 pin) { return; } - exti_detach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit)); + exti_detach_interrupt((afio_exti_num)(pin&0x0F)); } static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) { diff --git a/STM32F4/cores/maple/ext_interrupts.h b/STM32F4/cores/maple/ext_interrupts.h index b5c6f98..fe215dc 100644 --- a/STM32F4/cores/maple/ext_interrupts.h +++ b/STM32F4/cores/maple/ext_interrupts.h @@ -24,8 +24,8 @@ * SOFTWARE. *****************************************************************************/ -#include "libmaple_types.h" -#include "nvic.h" +#ifndef _EXT_INTERRUPTS_H_ +#define _EXT_INTERRUPTS_H_ /** * @file ext_interrupts.h @@ -33,8 +33,9 @@ * @brief Wiring-like external interrupt prototypes and types. */ -#ifndef _EXT_INTERRUPTS_H_ -#define _EXT_INTERRUPTS_H_ +#include +#include + /** * The kind of transition on an external pin which should trigger an diff --git a/STM32F4/cores/maple/hooks.c b/STM32F4/cores/maple/hooks.c new file mode 100644 index 0000000..641eabc --- /dev/null +++ b/STM32F4/cores/maple/hooks.c @@ -0,0 +1,31 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * Empty yield() hook. + * + * This function is intended to be used by library writers to build + * libraries or sketches that supports cooperative threads. + * + * Its defined as a weak symbol and it can be redefined to implement a + * real cooperative scheduler. + */ +static void __empty() { + // Empty +} +void yield(void) __attribute__ ((weak, alias("__empty"))); diff --git a/STM32F4/cores/maple/io.h b/STM32F4/cores/maple/io.h index df1ab96..aeaf0fd 100644 --- a/STM32F4/cores/maple/io.h +++ b/STM32F4/cores/maple/io.h @@ -33,8 +33,9 @@ #ifndef _IO_H_ #define _IO_H_ -#include "gpio.h" -#include "adc.h" +#include +#include +#include #include "wirish_time.h" @@ -179,9 +180,11 @@ static inline void toggleLED() { * accomplished portably over all LeafLabs boards by calling * pinMode(BOARD_BUTTON_PIN, INPUT). * + * @param button - one of available on-board buttons (up to 3 for generic F4) + * * @see pinMode() */ -uint8 isButtonPressed(); +uint8 isButtonPressed(uint8_t button); /** * Wait until the button is pressed and released, timing out if no @@ -195,12 +198,14 @@ uint8 isButtonPressed(); * button is pressed. If timeout_millis is left out (or 0), wait * forever. * + * @param button - one of available on-board buttons (up to 3 for generic F4) + * * @return true, if the button was pressed; false, if the timeout was * reached. * * @see pinMode() */ -uint8 waitForButtonPress(uint32 timeout_millis=0); +uint8 waitForButtonPress(uint8_t button, uint32 timeout_millis=0); /** * Shift out a byte of data, one bit at a time. diff --git a/STM32F4/cores/maple/itoa.c b/STM32F4/cores/maple/itoa.c index fc35766..33efd14 100644 --- a/STM32F4/cores/maple/itoa.c +++ b/STM32F4/cores/maple/itoa.c @@ -120,8 +120,12 @@ extern char* ltoa( long value, char *string, int radix ) return string; } - -extern char* utoa( unsigned long value, char *string, int radix ) +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \ + (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2))) +extern char* utoa( unsigned value, char *string, int radix ) +#else +extern char* utoa( unsigned int value, char *string, int radix ) +#endif { return ultoa( value, string, radix ) ; } diff --git a/STM32F4/cores/maple/itoa.h b/STM32F4/cores/maple/itoa.h index 59af109..a317e82 100644 --- a/STM32F4/cores/maple/itoa.h +++ b/STM32F4/cores/maple/itoa.h @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _ITOA_ -#define _ITOA_ +#ifndef _ITOA_H_ +#define _ITOA_H_ #ifdef __cplusplus extern "C"{ @@ -31,7 +31,12 @@ extern void itoa( int n, char s[] ) ; extern char* itoa( int value, char *string, int radix ) ; extern char* ltoa( long value, char *string, int radix ) ; -extern char* utoa( unsigned long value, char *string, int radix ) ; +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \ + (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2))) +extern char* utoa( unsigned value, char *string, int radix ) ; +#else +extern char* utoa( unsigned int value, char *string, int radix ) ; +#endif extern char* ultoa( unsigned long value, char *string, int radix ) ; #endif /* 0 */ diff --git a/STM32F4/cores/maple/libmaple/HardwareSPI.cpp b/STM32F4/cores/maple/libmaple/HardwareSPI.cpp deleted file mode 100644 index a5b4711..0000000 --- a/STM32F4/cores/maple/libmaple/HardwareSPI.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @author Marti Bolivar - * @brief Wirish SPI implementation. - */ - -#include "HardwareSPI.h" - -#include "timer.h" -#include "util.h" -#include "rcc.h" - -#include "wirish.h" -#include "boards.h" - -struct spi_pins { - uint8 nss; - uint8 sck; - uint8 miso; - uint8 mosi; -}; - -static const spi_pins* dev_to_spi_pins(spi_dev *dev); - -static void enable_device(spi_dev *dev, - bool as_master, - SPIFrequency frequency, - spi_cfg_flag endianness, - spi_mode mode); - -static const spi_pins board_spi_pins[] __FLASH__ = { - {BOARD_SPI1_NSS_PIN, - BOARD_SPI1_SCK_PIN, - BOARD_SPI1_MISO_PIN, - BOARD_SPI1_MOSI_PIN}, -#ifdef BOARD_SPI2_NSS_PIN - {BOARD_SPI2_NSS_PIN, - BOARD_SPI2_SCK_PIN, - BOARD_SPI2_MISO_PIN, - BOARD_SPI2_MOSI_PIN}, -#endif -#ifdef STM32_HIGH_DENSITY - {BOARD_SPI3B_NSS_PIN, - BOARD_SPI3B_SCK_PIN, - BOARD_SPI3B_MISO_PIN, - BOARD_SPI3B_MOSI_PIN}, -#endif -#ifdef STM32F4 - {BOARD_SPI3B_NSS_PIN, - BOARD_SPI3B_SCK_PIN, - BOARD_SPI3B_MISO_PIN, - BOARD_SPI3B_MOSI_PIN}, -#endif -}; - - -/* - * Constructor - */ - -HardwareSPI::HardwareSPI(uint32 spi_num) { - switch (spi_num) { - case 1: - this->spi_d = SPI1; - break; - case 2: - this->spi_d = SPI2; - break; -#ifdef STM32_HIGH_DENSITY - case 3: - this->spi_d = SPI3; - break; -#endif -#ifdef STM32F4 -// case 4: -// this->spi_d = SPI4; -// break; -#endif - default: - ASSERT(0); - } -} - -/* - * Set up/tear down - */ - -void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) { - if (mode >= 4) { - ASSERT(0); - return; - } - spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; - spi_mode m = (spi_mode)mode; - enable_device(this->spi_d, true, frequency, end, m); -} - -void HardwareSPI::begin(void) { - this->begin(SPI_1_125MHZ, MSBFIRST, 0); -} - -void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) { - if (mode >= 4) { - ASSERT(0); - return; - } - spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; - spi_mode m = (spi_mode)mode; - enable_device(this->spi_d, false, (SPIFrequency)0, end, m); -} - -void HardwareSPI::beginSlave(void) { - this->beginSlave(MSBFIRST, 0); -} - - -/* -void HardwareSPI::beginTransaction(uint8_t pin, SPISettings settings) -{ -// this->begin(settings.clock, settings.bitOrder, settings.dataMode); - this->begin(SPI_1_125MHZ, settings.bitOrder, settings.dataMode); -} -*/ - -void HardwareSPI::end(void) { - if (!spi_is_enabled(this->spi_d)) { - return; - } - - // Follows RM0008's sequence for disabling a SPI in master/slave - // full duplex mode. - while (spi_is_rx_nonempty(this->spi_d)) { - // FIXME [0.1.0] remove this once you have an interrupt based driver - volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); - } - while (!spi_is_tx_empty(this->spi_d)) - ; - while (spi_is_busy(this->spi_d)) - ; - spi_peripheral_disable(this->spi_d); -} - -/* - * I/O - */ - -uint8 HardwareSPI::read(void) { - uint8 buf[1]; - this->read(buf, 1); - return buf[0]; -} - -void HardwareSPI::read(uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (rxed < len) { - while (!spi_is_rx_nonempty(this->spi_d)) - ; - buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); - } -} - -#if 0 -void HardwareSPI::readMaster(uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (rxed < len) { - spi_tx_reg(this->spi_d, 0xff); - while (!spi_is_rx_nonempty(this->spi_d)) - ; - buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); - buf[rxed++] = this->spi_d->regs->DR; - } -} -#endif -void HardwareSPI::readMaster(uint8 *buf, uint32 len) { - spi_reg_map *r = this->spi_d->regs; - uint32 rxed = 0; - while (rxed < len) { - r->DR = 0xff; - while (!(r->SR & SPI_SR_RXNE)) - ; - buf[rxed++] = r->DR; - } -} - - -void HardwareSPI::waitReady() { - while (!spi_is_rx_nonempty(this->spi_d)) - ; -} - -void HardwareSPI::write(uint8 byte) { - this->write(&byte, 1); -} - -void HardwareSPI::write(const uint8 *data, uint32 length) { - uint32 txed = 0; - while (txed < length) { - txed += spi_tx(this->spi_d, data + txed, length - txed); - } -} - -uint8 HardwareSPI::transfer(uint8 byte) { - this->write(byte); - return this->read(); -} - -/* - * Pin accessors - */ - -uint8 HardwareSPI::misoPin(void) { - return dev_to_spi_pins(this->spi_d)->miso; -} - -uint8 HardwareSPI::mosiPin(void) { - return dev_to_spi_pins(this->spi_d)->mosi; -} - -uint8 HardwareSPI::sckPin(void) { - return dev_to_spi_pins(this->spi_d)->sck; -} - -uint8 HardwareSPI::nssPin(void) { - return dev_to_spi_pins(this->spi_d)->nss; -} - -/* - * Deprecated functions - */ - -uint8 HardwareSPI::send(uint8 data) { - uint8 buf[] = {data}; - return this->send(buf, 1); -} - -#if 1 -uint8 HardwareSPI::send(const uint8 *buf, uint32 len) { - uint32 txed = 0; - uint8 ret = 0; - while (txed < len) { - this->write(buf[txed++]); - ret = this->read(); - } - return ret; -} -#else -// this does not work for an unknown reason -uint8 HardwareSPI::send(const uint8 *buf, uint32 len) { - volatile uint32 *dr = &(this->spi_d->regs->DR); - volatile uint32 *sr = &(this->spi_d->regs->SR); - uint32 txed = 0; - uint32 rx=0; - while (txed < len) { - //while (!(*sr & SPI_SR_TXE)) - // ; - //*dr = buf[txed++]; - this->write(buf[txed++]); - - while (!(*sr & SPI_SR_RXNE)) - ; - rx = *dr; - //rx = this->read(); - } - - return rx; -} -#endif - -uint8 HardwareSPI::recv(void) { - return this->read(); -} - -/* - * Auxiliary functions - */ - -static void configure_gpios(spi_dev *dev, bool as_master); -static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq); - -static const spi_pins* dev_to_spi_pins(spi_dev *dev) { - switch (dev->clk_id) { - case RCC_SPI1: return board_spi_pins; - case RCC_SPI2: return board_spi_pins + 1; -#ifdef STM32_HIGH_DENSITY - case RCC_SPI3: return board_spi_pins + 2; -#endif -#ifdef STM32F4 - case RCC_SPI4: return board_spi_pins + 3; -#endif - default: return NULL; - } -} - -/* Enables the device in master or slave full duplex mode. If you - * change this code, you must ensure that appropriate changes are made - * to HardwareSPI::end(). */ -static void enable_device(spi_dev *dev, - bool as_master, - SPIFrequency freq, - spi_cfg_flag endianness, - spi_mode mode) { - spi_baud_rate baud = determine_baud_rate(dev, freq); - uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE | - (as_master ? SPI_SOFT_SS : 0)); - - spi_init(dev); - configure_gpios(dev, as_master); - if (as_master) { - spi_master_enable(dev, baud, mode, cfg_flags); - } else { - spi_slave_enable(dev, mode, cfg_flags); - } -} - -static void disable_pwm(const stm32_pin_info *i) { - if (i->timer_device) { - timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); - } -} - -static void configure_gpios(spi_dev *dev, bool as_master) { - const spi_pins *pins = dev_to_spi_pins(dev); - - if (!pins) { - return; - } - - const stm32_pin_info *nssi = (pins->nss >= 0) ? &PIN_MAP[pins->nss] : NULL; - const stm32_pin_info *scki = &PIN_MAP[pins->sck]; - const stm32_pin_info *misoi = &PIN_MAP[pins->miso]; - const stm32_pin_info *mosii = &PIN_MAP[pins->mosi]; - - if(nssi) { - disable_pwm(nssi); - } - disable_pwm(scki); - disable_pwm(misoi); - disable_pwm(mosii); - -#ifdef STM32F4 - if(dev->clk_id <= RCC_SPI2) { - if(nssi) { - if(!as_master) { - gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 5); - } - } - gpio_set_af_mode(scki->gpio_device, scki->gpio_bit, 5); - gpio_set_af_mode(misoi->gpio_device, misoi->gpio_bit, 5); - gpio_set_af_mode(mosii->gpio_device, mosii->gpio_bit, 5); - } else { - if(nssi) { - if(!as_master) { - gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 6); - } - } - gpio_set_af_mode(scki->gpio_device, scki->gpio_bit, 6); - gpio_set_af_mode(misoi->gpio_device, misoi->gpio_bit, 6); - gpio_set_af_mode(mosii->gpio_device, mosii->gpio_bit, 6); - } -#endif - - if(nssi) { - spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit, - scki->gpio_device, scki->gpio_bit, - misoi->gpio_device, misoi->gpio_bit, - mosii->gpio_device, mosii->gpio_bit); - } else { - spi_config_gpios(dev, as_master, NULL, -1, - scki->gpio_device, scki->gpio_bit, - misoi->gpio_device, misoi->gpio_bit, - mosii->gpio_device, mosii->gpio_bit); - } -} - -static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = { - SPI_BAUD_PCLK_DIV_2, - SPI_BAUD_PCLK_DIV_4, - SPI_BAUD_PCLK_DIV_8, - SPI_BAUD_PCLK_DIV_16, - SPI_BAUD_PCLK_DIV_32, - SPI_BAUD_PCLK_DIV_64, - SPI_BAUD_PCLK_DIV_128, - SPI_BAUD_PCLK_DIV_256, -}; - -/* - * Note: This assumes you're on a LeafLabs-style board - * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). - */ -static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) { - if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) { - /* APB2 peripherals are too fast for 140.625 KHz */ - ASSERT(0); - return (spi_baud_rate)~0; - } - return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ? - baud_rates[freq + 1] : - baud_rates[freq]); -} diff --git a/STM32F4/cores/maple/libmaple/HardwareSPI.h b/STM32F4/cores/maple/libmaple/HardwareSPI.h deleted file mode 100644 index 327f29d..0000000 --- a/STM32F4/cores/maple/libmaple/HardwareSPI.h +++ /dev/null @@ -1,279 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file HardwareSPI.h - * @brief High-level SPI interface - * - * This is a "bare essentials" polling driver for now. - */ - -/* TODO [0.1.0] Remove deprecated methods. */ - -#include "libmaple_types.h" -#include "spi.h" - -#include "boards.h" -#include "wirish.h" - -#ifndef _HARDWARESPI_H_ -#define _HARDWARESPI_H_ - -/** - * @brief Defines the possible SPI communication speeds. - */ -typedef enum SPIFrequency { - SPI_18MHZ = 0, /**< 18 MHz */ - SPI_9MHZ = 1, /**< 9 MHz */ - SPI_4_5MHZ = 2, /**< 4.5 MHz */ - SPI_2_25MHZ = 3, /**< 2.25 MHz */ - SPI_1_125MHZ = 4, /**< 1.125 MHz */ - SPI_562_500KHZ = 5, /**< 562.500 KHz */ - SPI_281_250KHZ = 6, /**< 281.250 KHz */ - SPI_140_625KHZ = 7, /**< 140.625 KHz */ -} SPIFrequency; - -#define MAX_SPI_FREQS 8 - -#if CYCLES_PER_MICROSECOND != 72 -/* TODO [0.2.0?] something smarter than this */ -//#warning "Unexpected clock speed; SPI frequency calculation will be incorrect" -#endif - - -//#define BOARD_SPI_DEFAULT_SS PC13 -#define BOARD_SPI_DEFAULT_SS PB0 -#define SPI_MODE0 SPI_MODE_0 -#define SPI_MODE1 SPI_MODE_1 -#define SPI_MODE2 SPI_MODE_2 -#define SPI_MODE3 SPI_MODE_3 - -/* -class SPISettings { -public: - SPISettings(uint32 clock, BitOrder bitOrder, uint8 dataMode) { - if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, dataMode); - } else { - init_MightInline(clock, bitOrder, dataMode); - } - } - SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } -private: - void init_MightInline(uint32 clock, BitOrder bitOrder, uint8 dataMode) { - init_AlwaysInline(clock, bitOrder, dataMode); - } - void init_AlwaysInline(uint32 clock, BitOrder bitOrder, uint8 dataMode) __attribute__((__always_inline__)) { - this->clock = clock; - this->bitOrder = bitOrder; - this->dataMode = dataMode; - } - uint32 clock; - BitOrder bitOrder; - uint8 dataMode; - friend class HardwareSPI; -}; -*/ - - -/** - * @brief Wirish SPI interface. - * - * This implementation uses software slave management, so the caller - * is responsible for controlling the slave select line. - */ -class HardwareSPI { -public: - /** - * @param spiPortNumber Number of the SPI port to manage. - */ - HardwareSPI(uint32 spiPortNumber); - - /* - * Set up/tear down - */ - - /** - * @brief Turn on a SPI port and set its GPIO pin modes for use as master. - * - * SPI port is enabled in full duplex mode, with software slave management. - * - * @param frequency Communication frequency - * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST (big-endian) - * @param mode SPI mode to use, one of SPI_MODE_0, SPI_MODE_1, - * SPI_MODE_2, and SPI_MODE_3. - */ - void begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode); - - /** - * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). - */ - void begin(void); - - /** - * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave. - * - * SPI port is enabled in full duplex mode, with software slave management. - * - * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian) - * @param mode SPI mode to use - */ - void beginSlave(uint32 bitOrder, uint32 mode); - - /** - * @brief Equivalent to beginSlave(MSBFIRST, 0). - */ - void beginSlave(void); - - /** - * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged. - */ - void end(void); - - /* - * I/O - */ - - /** - * @brief Return the next unread byte. - * - * If there is no unread byte waiting, this function will block - * until one is received. - */ - uint8 read(void); - - /** - * @brief Read length bytes, storing them into buffer. - * @param buffer Buffer to store received bytes into. - * @param length Number of bytes to store in buffer. This - * function will block until the desired number of - * bytes have been read. - */ - void read(uint8 *buffer, uint32 length); - - /** - * @brief Read length bytes, storing them into buffer. - * @param buffer Buffer to store received bytes into. - * @param length Number of bytes to store in buffer. This - * function will block until the desired number of - * bytes have been read. - */ - void readMaster(uint8 *buffer, uint32 length); - - - void waitReady(); - /** - * @brief Transmit a byte. - * @param data Byte to transmit. - */ - void write(uint8 data); - - /** - * @brief Transmit multiple bytes. - * @param buffer Bytes to transmit. - * @param length Number of bytes in buffer to transmit. - */ - void write(const uint8 *buffer, uint32 length); - - /** - * @brief Transmit a byte, then return the next unread byte. - * - * This function transmits before receiving. - * - * @param data Byte to transmit. - * @return Next unread byte. - */ - uint8 transfer(uint8 data); - - /* - * Pin accessors - */ - - /** - * @brief Return the number of the MISO (master in, slave out) pin - */ - uint8 misoPin(void); - - /** - * @brief Return the number of the MOSI (master out, slave in) pin - */ - uint8 mosiPin(void); - - /** - * @brief Return the number of the SCK (serial clock) pin - */ - uint8 sckPin(void); - - /** - * @brief Return the number of the NSS (slave select) pin - */ - uint8 nssPin(void); - - /* -- The following methods are deprecated --------------------------- */ - - /** - * @brief Deprecated. - * - * Use HardwareSPI::transfer() instead. - * - * @see HardwareSPI::transfer() - */ - uint8 send(uint8 data); - - /** - * @brief Deprecated. - * - * Use HardwareSPI::write() in combination with - * HardwareSPI::read() (or HardwareSPI::transfer()) instead. - * - * @see HardwareSPI::write() - * @see HardwareSPI::read() - * @see HardwareSPI::transfer() - */ - uint8 send(const uint8 *data, uint32 length); - - /** - * @brief Deprecated. - * - * Use HardwareSPI::read() instead. - * - * @see HardwareSPI::read() - */ - uint8 recv(void); - -// void beginTransaction(SPISettings settings) { beginTransaction(BOARD_SPI_DEFAULT_SS, settings); } -// void beginTransaction(uint8 pin, SPISettings settings); - void endTransaction(void) { } - -private: - spi_dev *spi_d; -}; - - -extern HardwareSPI SPI; - -#endif - diff --git a/STM32F4/cores/maple/libmaple/HardwareSerial.cpp b/STM32F4/cores/maple/libmaple/HardwareSerial.cpp index 59ce71d..7f3d281 100644 --- a/STM32F4/cores/maple/libmaple/HardwareSerial.cpp +++ b/STM32F4/cores/maple/libmaple/HardwareSerial.cpp @@ -56,19 +56,19 @@ #define RX5 BOARD_UART5_RX_PIN #endif -HardwareSerial Serial(USART1, TX1, RX1); +HardwareSerial Serial1(USART1, TX1, RX1); #ifdef TX2 -HardwareSerial Serial1(USART2, TX2, RX2); +HardwareSerial Serial2(USART2, TX2, RX2); #endif #ifdef TX3 -HardwareSerial Serial2(USART3, TX3, RX3); +HardwareSerial Serial3(USART3, TX3, RX3); #endif #if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) -HardwareSerial Serial3(UART4, TX4, RX4); -HardwareSerial Serial4(UART5, TX5, RX5); +HardwareSerial Serial4(UART4, TX4, RX4); +HardwareSerial Serial5(UART5, TX5, RX5); #endif HardwareSerial::HardwareSerial(usart_dev *usart_device, @@ -90,25 +90,23 @@ void HardwareSerial::begin(uint32 baud) { return; } - const stm32_pin_info *txi = &PIN_MAP[tx_pin]; - const stm32_pin_info *rxi = &PIN_MAP[rx_pin]; -#ifdef STM32F2 +#ifdef STM32F4 // int af = 7<<8; if (usart_device == UART4 || usart_device == UART5) { - gpio_set_af_mode(txi->gpio_device, txi->gpio_bit, 8); - gpio_set_af_mode(rxi->gpio_device, rxi->gpio_bit, 8); + gpio_set_af_mode(tx_pin, 8); + gpio_set_af_mode(rx_pin, 8); } else { - gpio_set_af_mode(txi->gpio_device, txi->gpio_bit, 7); - gpio_set_af_mode(rxi->gpio_device, rxi->gpio_bit, 7); + gpio_set_af_mode(tx_pin, 7); + gpio_set_af_mode(rx_pin, 7); } - gpio_set_mode(txi->gpio_device, txi->gpio_bit, (gpio_pin_mode)(GPIO_AF_OUTPUT_PP | GPIO_PUPD_INPUT_PU | 0x700)); - gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, (gpio_pin_mode)(GPIO_MODE_AF | GPIO_PUPD_INPUT_PU | 0x700)); + gpio_set_mode(tx_pin, (gpio_pin_mode)(GPIO_AF_OUTPUT_PP_PU | 0x700)); + gpio_set_mode(rx_pin, (gpio_pin_mode)(GPIO_AF_INPUT_PU | 0x700)); //gpio_set_mode(txi->gpio_device, txi->gpio_bit, (gpio_pin_mode)(GPIO_PUPD_INPUT_PU)); //gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, (gpio_pin_mode)(GPIO_PUPD_INPUT_PU)); #else - gpio_set_mode(txi->gpio_device, txi->gpio_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(tx_pin, GPIO_AF_OUTPUT_PP); + gpio_set_mode(rx_pin, GPIO_INPUT_FLOATING); #endif #if 0 if (txi->timer_device != NULL) { diff --git a/STM32F4/cores/maple/libmaple/HardwareSerial.h b/STM32F4/cores/maple/libmaple/HardwareSerial.h index c09fe54..b49c4cf 100644 --- a/STM32F4/cores/maple/libmaple/HardwareSerial.h +++ b/STM32F4/cores/maple/libmaple/HardwareSerial.h @@ -57,6 +57,7 @@ public: void begin(uint32 baud); void end(void); + operator bool() { return true; } // This is needed because of "if (!Serial)" /* I/O */ virtual int available(void); virtual int peek(void); @@ -75,12 +76,12 @@ private: uint8 rx_pin; }; -extern HardwareSerial Serial; extern HardwareSerial Serial1; extern HardwareSerial Serial2; #if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) extern HardwareSerial Serial3; extern HardwareSerial Serial4; +extern HardwareSerial Serial5; #endif extern HardwareSerial &SerialDebug; #endif diff --git a/STM32F4/cores/maple/libmaple/adc.c b/STM32F4/cores/maple/libmaple/adc.c index aeeb43c..f44156d 100644 --- a/STM32F4/cores/maple/libmaple/adc.c +++ b/STM32F4/cores/maple/libmaple/adc.c @@ -41,27 +41,24 @@ #include "rcc.h" #include "adc.h" -static adc_dev adc1 = { +/** ADC1 device. */ +const adc_dev ADC1 = { .regs = ADC1_BASE, .clk_id = RCC_ADC1 }; -/** ADC1 device. */ -const adc_dev *ADC1 = &adc1; -static adc_dev adc2 = { +/** ADC2 device. */ +const adc_dev ADC2 = { .regs = ADC2_BASE, .clk_id = RCC_ADC2 }; -/** ADC2 device. */ -const adc_dev *ADC2 = &adc2; #ifdef STM32_HIGH_DENSITY -adc_dev adc3 = { +/** ADC3 device. */ +const adc_dev ADC3 = { .regs = ADC3_BASE, .clk_id = RCC_ADC3 }; -/** ADC3 device. */ -const adc_dev *ADC3 = &adc3; #endif /** @@ -74,7 +71,7 @@ const adc_dev *ADC3 = &adc3; */ void adc_init(const adc_dev *dev) { rcc_clk_enable(dev->clk_id); -#ifdef STM32F2 +#ifdef STM32F4 if(dev->clk_id == RCC_ADC1) { rcc_reset_dev(dev->clk_id); } @@ -101,10 +98,10 @@ void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) { * @param fn Function to call on each ADC device. */ void adc_foreach(void (*fn)(const adc_dev*)) { - fn(ADC1); - fn(ADC2); + fn(&ADC1); + fn(&ADC2); #ifdef STM32_HIGH_DENSITY - fn(ADC3); + fn(&ADC3); #endif } @@ -136,10 +133,12 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) { * @brief Calibrate an ADC peripheral * @param dev adc device */ -void adc_calibrate(const adc_dev *dev) { +void adc_calibrate(const adc_dev *dev) +{ +/* #ifndef STM32F2 - __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); - __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); + __IO uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); + __IO uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); *rstcal_bit = 1; while (*rstcal_bit) @@ -149,6 +148,7 @@ void adc_calibrate(const adc_dev *dev) { while (*cal_bit) ; #endif +*/ } /** @@ -171,8 +171,8 @@ uint16 adc_read(const adc_dev *dev, uint8 channel) { return (uint16)(regs->DR & ADC_DR_DATA); } -void setupADC_F2() { -#ifdef STM32F2 +void setupADC_F4(void) +{ uint32 tmpreg1 = 0; tmpreg1 = ADC_COMMON->CCR; @@ -196,5 +196,4 @@ void setupADC_F2() { /* Write to ADC CCR */ ADC_COMMON->CCR = tmpreg1; -#endif } diff --git a/STM32F4/cores/maple/libmaple/adc.h b/STM32F4/cores/maple/libmaple/adc.h index 3a40d4c..398c242 100644 --- a/STM32F4/cores/maple/libmaple/adc.h +++ b/STM32F4/cores/maple/libmaple/adc.h @@ -42,40 +42,38 @@ extern "C"{ #endif -#ifdef STM32F2 - typedef struct - { - __io uint32 CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */ - __io uint32 CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */ - __io uint32 CDR; /*!< ADC common regular data register for dual - AND triple modes, Address offset: ADC1 base address + 0x308 */ - } ADC_Common_TypeDef; +typedef struct +{ + __IO uint32 CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */ + __IO uint32 CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */ + __IO uint32 CDR; /*!< ADC common regular data register for dual + AND triple modes, Address offset: ADC1 base address + 0x308 */ +} ADC_Common_TypeDef; #define ADC_COMMON ((ADC_Common_TypeDef *) 0x40012300) -#endif /** ADC register map type. */ typedef struct adc_reg_map { - __io uint32 SR; ///< Status register - __io uint32 CR1; ///< Control register 1 - __io uint32 CR2; ///< Control register 2 - __io uint32 SMPR1; ///< Sample time register 1 - __io uint32 SMPR2; ///< Sample time register 2 - __io uint32 JOFR1; ///< Injected channel data offset register 1 - __io uint32 JOFR2; ///< Injected channel data offset register 2 - __io uint32 JOFR3; ///< Injected channel data offset register 3 - __io uint32 JOFR4; ///< Injected channel data offset register 4 - __io uint32 HTR; ///< Watchdog high threshold register - __io uint32 LTR; ///< Watchdog low threshold register - __io uint32 SQR1; ///< Regular sequence register 1 - __io uint32 SQR2; ///< Regular sequence register 2 - __io uint32 SQR3; ///< Regular sequence register 3 - __io uint32 JSQR; ///< Injected sequence register - __io uint32 JDR1; ///< Injected data register 1 - __io uint32 JDR2; ///< Injected data register 2 - __io uint32 JDR3; ///< Injected data register 3 - __io uint32 JDR4; ///< Injected data register 4 - __io uint32 DR; ///< Regular data register + __IO uint32 SR; ///< Status register + __IO uint32 CR1; ///< Control register 1 + __IO uint32 CR2; ///< Control register 2 + __IO uint32 SMPR1; ///< Sample time register 1 + __IO uint32 SMPR2; ///< Sample time register 2 + __IO uint32 JOFR1; ///< Injected channel data offset register 1 + __IO uint32 JOFR2; ///< Injected channel data offset register 2 + __IO uint32 JOFR3; ///< Injected channel data offset register 3 + __IO uint32 JOFR4; ///< Injected channel data offset register 4 + __IO uint32 HTR; ///< Watchdog high threshold register + __IO uint32 LTR; ///< Watchdog low threshold register + __IO uint32 SQR1; ///< Regular sequence register 1 + __IO uint32 SQR2; ///< Regular sequence register 2 + __IO uint32 SQR3; ///< Regular sequence register 3 + __IO uint32 JSQR; ///< Injected sequence register + __IO uint32 JDR1; ///< Injected data register 1 + __IO uint32 JDR2; ///< Injected data register 2 + __IO uint32 JDR3; ///< Injected data register 3 + __IO uint32 JDR4; ///< Injected data register 4 + __IO uint32 DR; ///< Regular data register } adc_reg_map; /** ADC device type. */ @@ -84,33 +82,22 @@ typedef struct adc_dev { rcc_clk_id clk_id; /**< RCC clock information */ } adc_dev; -extern const adc_dev *ADC1; -extern const adc_dev *ADC2; +extern const adc_dev ADC1; +extern const adc_dev ADC2; #ifdef STM32_HIGH_DENSITY -extern const adc_dev *ADC3; +extern const adc_dev ADC3; #endif /* * Register map base pointers */ -#ifdef STM32F2 - /** ADC1 register map base pointer. */ - #define ADC1_BASE ((struct adc_reg_map*)0x40012000) - /** ADC2 register map base pointer. */ - #define ADC2_BASE ((struct adc_reg_map*)0x40012100) - /** ADC3 register map base pointer. */ - #define ADC3_BASE ((struct adc_reg_map*)0x40012200) -#else - /** ADC1 register map base pointer. */ - #define ADC1_BASE ((struct adc_reg_map*)0x40012400) - /** ADC2 register map base pointer. */ - #define ADC2_BASE ((struct adc_reg_map*)0x40012800) - #ifdef STM32_HIGH_DENSITY - /** ADC3 register map base pointer. */ - #define ADC3_BASE ((struct adc_reg_map*)0x40013C00) - #endif -#endif +/** ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012000) +/** ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012100) +/** ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40012200) /* * Register bit definitions @@ -166,18 +153,11 @@ extern const adc_dev *ADC3; #define ADC_CR2_ALIGN_BIT 11 #define ADC_CR2_JEXTTRIG_BIT 15 #define ADC_CR2_EXTTRIG_BIT 20 -#define ADC_CR2_TSEREFE_BIT 23 -#ifdef STM32F2 +#define ADC_CR2_TSVREFE_BIT 23 #define ADC_CR2_JSWSTART_BIT 22 #define ADC_CR2_SWSTART_BIT 30 #define ADC_CR2_EXTSEL (0x0F000000) #define ADC_CR2_JEXTSEL (0x000F0000) -#else -#define ADC_CR2_JSWSTART_BIT 21 -#define ADC_CR2_SWSTART_BIT 22 -#define ADC_CR2_EXTSEL (0x000E0000) -#define ADC_CR2_JEXTSEL (0x00007000) -#endif @@ -191,7 +171,7 @@ extern const adc_dev *ADC3; #define ADC_CR2_EXTTRIG BIT(ADC_CR2_EXTTRIG_BIT) #define ADC_CR2_JSWSTART BIT(ADC_CR2_JSWSTART_BIT) #define ADC_CR2_SWSTART BIT(ADC_CR2_SWSTART_BIT) -#define ADC_CR2_TSEREFE BIT(ADC_CR2_TSEREFE_BIT) +#define ADC_CR2_TSVREFE BIT(ADC_CR2_TSVREFE_BIT) /* Sample time register 1 */ @@ -388,7 +368,7 @@ static inline void adc_disable_all(void) { adc_foreach(adc_disable); } -void setupADC_F2(); +extern void setupADC_F4(void); #ifdef __cplusplus } // extern "C" diff --git a/STM32F4/cores/maple/libmaple/bkp.c b/STM32F4/cores/maple/libmaple/bkp.c index 7d1ad7f..a923e77 100644 --- a/STM32F4/cores/maple/libmaple/bkp.c +++ b/STM32F4/cores/maple/libmaple/bkp.c @@ -34,7 +34,7 @@ #include "rcc.h" #include "bitband.h" -static inline __io uint32* data_register(uint8 reg); +static inline __IO uint32* data_register(uint8 reg); bkp_dev bkp = { .regs = BKP_BASE, @@ -78,7 +78,7 @@ void bkp_disable_writes(void) { * medium-density devices, 42 on high-density devices). */ uint16 bkp_read(uint8 reg) { - __io uint32* dr = data_register(reg); + __IO uint32* dr = data_register(reg); if (!dr) { ASSERT(0); /* nonexistent register */ return 0; @@ -97,7 +97,7 @@ uint16 bkp_read(uint8 reg) { * @see bkp_enable_writes() */ void bkp_write(uint8 reg, uint16 val) { - __io uint32* dr = data_register(reg); + __IO uint32* dr = data_register(reg); if (!dr) { ASSERT(0); /* nonexistent register */ return; @@ -112,7 +112,7 @@ void bkp_write(uint8 reg, uint16 val) { */ #define NR_LOW_DRS 10 -static inline __io uint32* data_register(uint8 reg) { +static inline __IO uint32* data_register(uint8 reg) { if (reg < 1 || reg > BKP_NR_DATA_REGS) { return 0; } diff --git a/STM32F4/cores/maple/libmaple/bkp.h b/STM32F4/cores/maple/libmaple/bkp.h index a81267d..44754a3 100644 --- a/STM32F4/cores/maple/libmaple/bkp.h +++ b/STM32F4/cores/maple/libmaple/bkp.h @@ -47,59 +47,59 @@ extern "C" { /** Backup peripheral register map type. */ typedef struct bkp_reg_map { const uint32 RESERVED1; ///< Reserved - __io uint32 DR1; ///< Data register 1 - __io uint32 DR2; ///< Data register 2 - __io uint32 DR3; ///< Data register 3 - __io uint32 DR4; ///< Data register 4 - __io uint32 DR5; ///< Data register 5 - __io uint32 DR6; ///< Data register 6 - __io uint32 DR7; ///< Data register 7 - __io uint32 DR8; ///< Data register 8 - __io uint32 DR9; ///< Data register 9 - __io uint32 DR10; ///< Data register 10 - __io uint32 RTCCR; ///< RTC control register - __io uint32 CR; ///< Control register - __io uint32 CSR; ///< Control and status register + __IO uint32 DR1; ///< Data register 1 + __IO uint32 DR2; ///< Data register 2 + __IO uint32 DR3; ///< Data register 3 + __IO uint32 DR4; ///< Data register 4 + __IO uint32 DR5; ///< Data register 5 + __IO uint32 DR6; ///< Data register 6 + __IO uint32 DR7; ///< Data register 7 + __IO uint32 DR8; ///< Data register 8 + __IO uint32 DR9; ///< Data register 9 + __IO uint32 DR10; ///< Data register 10 + __IO uint32 RTCCR; ///< RTC control register + __IO uint32 CR; ///< Control register + __IO uint32 CSR; ///< Control and status register #ifdef STM32_HIGH_DENSITY const uint32 RESERVED2; ///< Reserved const uint32 RESERVED3; ///< Reserved - __io uint32 DR11; ///< Data register 11 - __io uint32 DR12; ///< Data register 12 - __io uint32 DR13; ///< Data register 13 - __io uint32 DR14; ///< Data register 14 - __io uint32 DR15; ///< Data register 15 - __io uint32 DR16; ///< Data register 16 - __io uint32 DR17; ///< Data register 17 - __io uint32 DR18; ///< Data register 18 - __io uint32 DR19; ///< Data register 19 - __io uint32 DR20; ///< Data register 20 - __io uint32 DR21; ///< Data register 21 - __io uint32 DR22; ///< Data register 22 - __io uint32 DR23; ///< Data register 23 - __io uint32 DR24; ///< Data register 24 - __io uint32 DR25; ///< Data register 25 - __io uint32 DR26; ///< Data register 26 - __io uint32 DR27; ///< Data register 27 - __io uint32 DR28; ///< Data register 28 - __io uint32 DR29; ///< Data register 29 - __io uint32 DR30; ///< Data register 30 - __io uint32 DR31; ///< Data register 31 - __io uint32 DR32; ///< Data register 32 - __io uint32 DR33; ///< Data register 33 - __io uint32 DR34; ///< Data register 34 - __io uint32 DR35; ///< Data register 35 - __io uint32 DR36; ///< Data register 36 - __io uint32 DR37; ///< Data register 37 - __io uint32 DR38; ///< Data register 38 - __io uint32 DR39; ///< Data register 39 - __io uint32 DR40; ///< Data register 40 - __io uint32 DR41; ///< Data register 41 - __io uint32 DR42; ///< Data register 42 + __IO uint32 DR11; ///< Data register 11 + __IO uint32 DR12; ///< Data register 12 + __IO uint32 DR13; ///< Data register 13 + __IO uint32 DR14; ///< Data register 14 + __IO uint32 DR15; ///< Data register 15 + __IO uint32 DR16; ///< Data register 16 + __IO uint32 DR17; ///< Data register 17 + __IO uint32 DR18; ///< Data register 18 + __IO uint32 DR19; ///< Data register 19 + __IO uint32 DR20; ///< Data register 20 + __IO uint32 DR21; ///< Data register 21 + __IO uint32 DR22; ///< Data register 22 + __IO uint32 DR23; ///< Data register 23 + __IO uint32 DR24; ///< Data register 24 + __IO uint32 DR25; ///< Data register 25 + __IO uint32 DR26; ///< Data register 26 + __IO uint32 DR27; ///< Data register 27 + __IO uint32 DR28; ///< Data register 28 + __IO uint32 DR29; ///< Data register 29 + __IO uint32 DR30; ///< Data register 30 + __IO uint32 DR31; ///< Data register 31 + __IO uint32 DR32; ///< Data register 32 + __IO uint32 DR33; ///< Data register 33 + __IO uint32 DR34; ///< Data register 34 + __IO uint32 DR35; ///< Data register 35 + __IO uint32 DR36; ///< Data register 36 + __IO uint32 DR37; ///< Data register 37 + __IO uint32 DR38; ///< Data register 38 + __IO uint32 DR39; ///< Data register 39 + __IO uint32 DR40; ///< Data register 40 + __IO uint32 DR41; ///< Data register 41 + __IO uint32 DR42; ///< Data register 42 #endif } bkp_reg_map; /** Backup peripheral register map base pointer. */ -#define BKP_BASE ((struct bkp_reg_map*)0x40006C00) +#define BKP_BASE ((struct bkp_reg_map*)0x40024000) /** Backup peripheral device type. */ typedef struct bkp_dev { diff --git a/STM32F4/cores/maple/libmaple/dac.c b/STM32F4/cores/maple/libmaple/dac.c index 264e4e2..3853f90 100644 --- a/STM32F4/cores/maple/libmaple/dac.c +++ b/STM32F4/cores/maple/libmaple/dac.c @@ -126,11 +126,11 @@ void dac_enable_channel(const dac_dev *dev, uint8 channel) { */ switch (channel) { case 1: - gpio_set_mode(GPIOA, 4, GPIO_INPUT_ANALOG); + gpio_set_mode((uint8_t)PA4, GPIO_INPUT_ANALOG); dev->regs->CR |= DAC_CR_EN1; break; case 2: - gpio_set_mode(GPIOA, 5, GPIO_INPUT_ANALOG); + gpio_set_mode((uint8_t)PA5, GPIO_INPUT_ANALOG); dev->regs->CR |= DAC_CR_EN2; break; } diff --git a/STM32F4/cores/maple/libmaple/dac.h b/STM32F4/cores/maple/libmaple/dac.h index dd1b22b..6c5f2e8 100644 --- a/STM32F4/cores/maple/libmaple/dac.h +++ b/STM32F4/cores/maple/libmaple/dac.h @@ -46,28 +46,28 @@ extern "C"{ /** DAC register map. */ typedef struct dac_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 SWTRIGR; /**< Software trigger register */ - __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + __IO uint32 CR; /**< Control register */ + __IO uint32 SWTRIGR; /**< Software trigger register */ + __IO uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data holding register */ - __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + __IO uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data holding register */ - __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + __IO uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data holding register */ - __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + __IO uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data holding register */ - __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + __IO uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data holding register */ - __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + __IO uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data holding register */ - __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + __IO uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data holding register */ - __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + __IO uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data holding register */ - __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + __IO uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding register */ - __io uint32 DOR1; /**< Channel 1 data output register */ - __io uint32 DOR2; /**< Channel 2 data output register */ + __IO uint32 DOR1; /**< Channel 1 data output register */ + __IO uint32 DOR2; /**< Channel 2 data output register */ } dac_reg_map; /** DAC register map base address */ diff --git a/STM32F4/cores/maple/libmaple/dma.h b/STM32F4/cores/maple/libmaple/dma.h index a965c03..420adf8 100644 --- a/STM32F4/cores/maple/libmaple/dma.h +++ b/STM32F4/cores/maple/libmaple/dma.h @@ -30,9 +30,4 @@ * @brief Direct Memory Access peripheral support */ -#ifdef STM32F2 -#include "dmaF2.h" -#include -#else -#include "dmaF1.h" -#endif +#include "dmaF4.h" diff --git a/STM32F4/cores/maple/libmaple/dmaF1.c b/STM32F4/cores/maple/libmaple/dmaF1.c deleted file mode 100644 index f8ddb2d..0000000 --- a/STM32F4/cores/maple/libmaple/dmaF1.c +++ /dev/null @@ -1,383 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifdef STM32F1 - -/** - * @file dma.c - * @author Marti Bolivar ; - * Original implementation by Michael Hope - * @brief Direct Memory Access peripheral support - */ - -#include "dma.h" -#include "bitband.h" -#include "util.h" - -/* - * Devices - */ - -static dma_dev dma1 = { - .regs = DMA1_BASE, - .clk_id = RCC_DMA1, - .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH2 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH3 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH4 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH5 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH6 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH7 }} -}; -/** DMA1 device */ -dma_dev *DMA1 = &dma1; - -#ifdef STM32_HIGH_DENSITY -static dma_dev dma2 = { - .regs = DMA2_BASE, - .clk_id = RCC_DMA2, - .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH2 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH3 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }} /* !@#$ */ -}; -/** DMA2 device */ -dma_dev *DMA2 = &dma2; -#endif - -/* - * Convenience routines - */ - -/** - * @brief Initialize a DMA device. - * @param dev Device to initialize. - */ -void dma_init(dma_dev *dev) { - rcc_clk_enable(dev->clk_id); -} - -/** - * @brief Set up a DMA transfer. - * - * The channel will be disabled before being reconfigured. The - * transfer will have low priority by default. You may choose another - * priority before the transfer begins using dma_set_priority(), as - * well as performing any other configuration you desire. When the - * channel is configured to your liking, enable it using dma_enable(). - * - * @param dev DMA device. - * @param channel DMA channel. - * @param peripheral_address Base address of peripheral data register - * involved in the transfer. - * @param peripheral_size Peripheral data transfer size. - * @param memory_address Base memory address involved in the transfer. - * @param memory_size Memory data transfer size. - * @param mode Logical OR of dma_mode_flags - * @sideeffect Disables the given DMA channel. - * @see dma_xfer_size - * @see dma_mode_flags - * @see dma_set_num_transfers() - * @see dma_set_priority() - * @see dma_attach_interrupt() - * @see dma_enable() - */ -void dma_setup_transfer(dma_dev *dev, - dma_channel channel, - __io void *peripheral_address, - dma_xfer_size peripheral_size, - __io void *memory_address, - dma_xfer_size memory_size, - uint32 mode) { - dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel); - - dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */ - channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode; - channel_regs->CMAR = (uint32)memory_address; - channel_regs->CPAR = (uint32)peripheral_address; -} - -/** - * @brief Set the number of data to be transferred on a DMA channel. - * - * You may not call this function while the channel is enabled. - * - * @param dev DMA device - * @param channel Channel through which the transfer occurs. - * @param num_transfers - */ -void dma_set_num_transfers(dma_dev *dev, - dma_channel channel, - uint16 num_transfers) { - dma_channel_reg_map *channel_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - channel_regs = dma_channel_regs(dev, channel); - channel_regs->CNDTR = num_transfers; -} - -/** - * @brief Set the priority of a DMA transfer. - * - * You may not call this function while the channel is enabled. - * - * @param dev DMA device - * @param channel DMA channel - * @param priority priority to set. - */ -void dma_set_priority(dma_dev *dev, - dma_channel channel, - dma_priority priority) { - dma_channel_reg_map *channel_regs; - uint32 ccr; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - channel_regs = dma_channel_regs(dev, channel); - ccr = channel_regs->CCR; - ccr &= ~DMA_CCR_PL; - ccr |= priority; - channel_regs->CCR = ccr; -} - -/** - * @brief Attach an interrupt to a DMA transfer. - * - * Interrupts are enabled using appropriate mode flags in - * dma_setup_transfer(). - * - * @param dev DMA device - * @param channel Channel to attach handler to - * @param handler Interrupt handler to call when channel interrupt fires. - * @see dma_setup_transfer() - * @see dma_get_irq_cause() - * @see dma_detach_interrupt() - */ -void dma_attach_interrupt(dma_dev *dev, - dma_channel channel, - void (*handler)(void)) { - dev->handlers[channel - 1].handler = handler; - nvic_irq_enable(dev->handlers[channel - 1].irq_line); -} - -/** - * @brief Detach a DMA transfer interrupt handler. - * - * After calling this function, the given channel's interrupts will be - * disabled. - * - * @param dev DMA device - * @param channel Channel whose handler to detach - * @sideeffect Clears interrupt enable bits in the channel's CCR register. - * @see dma_attach_interrupt() - */ -void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { - /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ - dma_channel_regs(dev, channel)->CCR &= ~0xF; - dev->handlers[channel - 1].handler = NULL; -} - -/** - * @brief Discover the reason why a DMA interrupt was called. - * - * You may only call this function within an attached interrupt - * handler for the given channel. - * - * This function resets the internal DMA register state which encodes - * the cause of the interrupt; consequently, it can only be called - * once per interrupt handler invocation. - * - * @param dev DMA device - * @param channel Channel whose interrupt is being handled. - * @return Reason why the interrupt fired. - * @sideeffect Clears channel status flags in dev->regs->ISR. - * @see dma_attach_interrupt() - * @see dma_irq_cause - */ -dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) { - uint8 status_bits = dma_get_isr_bits(dev, channel); - - /* If the channel global interrupt flag is cleared, then - * something's very wrong. */ - ASSERT(status_bits & BIT(0)); - - dma_clear_isr_bits(dev, channel); - - /* ISR flags get set even if the corresponding interrupt enable - * bits in the channel's configuration register are cleared, so we - * can't use a switch here. - * - * Don't change the order of these if statements. */ - if (status_bits & BIT(3)) { - return DMA_TRANSFER_ERROR; - } else if (status_bits & BIT(1)) { - return DMA_TRANSFER_COMPLETE; - } else if (status_bits & BIT(2)) { - return DMA_TRANSFER_HALF_COMPLETE; - } else if (status_bits & BIT(0)) { - /* Shouldn't happen (unless someone messed up an IFCR write). */ - throb(); - } -#if DEBUG_LEVEL < DEBUG_ALL - else { - /* We shouldn't have been called, but the debug level is too - * low for the above ASSERT() to have had any effect. In - * order to fail fast, mimic the DMA controller's behavior - * when an error occurs. */ - dma_disable(dev, channel); - } -#endif - return DMA_TRANSFER_ERROR; -} - -/** - * @brief Enable a DMA channel. - * @param dev DMA device - * @param channel Channel to enable - */ -void dma_enable(dma_dev *dev, dma_channel channel) { - dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); - bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1); -} - -/** - * @brief Disable a DMA channel. - * @param dev DMA device - * @param channel Channel to disable - */ -void dma_disable(dma_dev *dev, dma_channel channel) { - dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); - bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0); -} - -/** - * @brief Set the base memory address where data will be read from or - * written to. - * - * You must not call this function while the channel is enabled. - * - * If the DMA memory size is 16 bits, the address is automatically - * aligned to a half-word. If the DMA memory size is 32 bits, the - * address is aligned to a word. - * - * @param dev DMA Device - * @param channel Channel whose base memory address to set. - * @param addr Memory base address to use. - */ -void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { - dma_channel_reg_map *chan_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - chan_regs = dma_channel_regs(dev, channel); - chan_regs->CMAR = (uint32)addr; -} - -/** - * @brief Set the base peripheral address where data will be read from - * or written to. - * - * You must not call this function while the channel is enabled. - * - * If the DMA peripheral size is 16 bits, the address is automatically - * aligned to a half-word. If the DMA peripheral size is 32 bits, the - * address is aligned to a word. - * - * @param dev DMA Device - * @param channel Channel whose peripheral data register base address to set. - * @param addr Peripheral memory base address to use. - */ -void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { - dma_channel_reg_map *chan_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - chan_regs = dma_channel_regs(dev, channel); - chan_regs->CPAR = (uint32)addr; -} - -/* - * IRQ handlers - */ - -static inline void dispatch_handler(dma_dev *dev, dma_channel channel) { - void (*handler)(void) = dev->handlers[channel - 1].handler; - if (handler) { - handler(); - dma_clear_isr_bits(dev, channel); /* in case handler doesn't */ - } -} - -void __irq_dma1_channel1(void) { - dispatch_handler(DMA1, DMA_CH1); -} - -void __irq_dma1_channel2(void) { - dispatch_handler(DMA1, DMA_CH2); -} - -void __irq_dma1_channel3(void) { - dispatch_handler(DMA1, DMA_CH3); -} - -void __irq_dma1_channel4(void) { - dispatch_handler(DMA1, DMA_CH4); -} - -void __irq_dma1_channel5(void) { - dispatch_handler(DMA1, DMA_CH5); -} - -void __irq_dma1_channel6(void) { - dispatch_handler(DMA1, DMA_CH6); -} - -void __irq_dma1_channel7(void) { - dispatch_handler(DMA1, DMA_CH7); -} - -#ifdef STM32_HIGH_DENSITY -void __irq_dma2_channel1(void) { - dispatch_handler(DMA2, DMA_CH1); -} - -void __irq_dma2_channel2(void) { - dispatch_handler(DMA2, DMA_CH2); -} - -void __irq_dma2_channel3(void) { - dispatch_handler(DMA2, DMA_CH3); -} - -void __irq_dma2_channel4_5(void) { - dispatch_handler(DMA2, DMA_CH4); - dispatch_handler(DMA2, DMA_CH5); -} -#endif - -#endif \ No newline at end of file diff --git a/STM32F4/cores/maple/libmaple/dmaF1.h b/STM32F4/cores/maple/libmaple/dmaF1.h deleted file mode 100644 index 6e8087f..0000000 --- a/STM32F4/cores/maple/libmaple/dmaF1.h +++ /dev/null @@ -1,453 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Michael Hope. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file dma.h - * - * @author Marti Bolivar ; - * Original implementation by Michael Hope - * - * @brief Direct Memory Access peripheral support - */ - -/* - * See /notes/dma.txt for more information. - */ - -#ifndef _DMA_H_ -#define _DMA_H_ - -#include "libmaple_types.h" -#include "rcc.h" -#include "nvic.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - * Register maps - */ - -/** - * @brief DMA register map type. - * - * Note that DMA controller 2 (register map base pointer DMA2_BASE) - * only supports channels 1--5. - */ -typedef struct dma_reg_map { - __io uint32 ISR; /**< Interrupt status register */ - __io uint32 IFCR; /**< Interrupt flag clear register */ - __io uint32 CCR1; /**< Channel 1 configuration register */ - __io uint32 CNDTR1; /**< Channel 1 number of data register */ - __io uint32 CPAR1; /**< Channel 1 peripheral address register */ - __io uint32 CMAR1; /**< Channel 1 memory address register */ - const uint32 RESERVED1; /**< Reserved. */ - __io uint32 CCR2; /**< Channel 2 configuration register */ - __io uint32 CNDTR2; /**< Channel 2 number of data register */ - __io uint32 CPAR2; /**< Channel 2 peripheral address register */ - __io uint32 CMAR2; /**< Channel 2 memory address register */ - const uint32 RESERVED2; /**< Reserved. */ - __io uint32 CCR3; /**< Channel 3 configuration register */ - __io uint32 CNDTR3; /**< Channel 3 number of data register */ - __io uint32 CPAR3; /**< Channel 3 peripheral address register */ - __io uint32 CMAR3; /**< Channel 3 memory address register */ - const uint32 RESERVED3; /**< Reserved. */ - __io uint32 CCR4; /**< Channel 4 configuration register */ - __io uint32 CNDTR4; /**< Channel 4 number of data register */ - __io uint32 CPAR4; /**< Channel 4 peripheral address register */ - __io uint32 CMAR4; /**< Channel 4 memory address register */ - const uint32 RESERVED4; /**< Reserved. */ - __io uint32 CCR5; /**< Channel 5 configuration register */ - __io uint32 CNDTR5; /**< Channel 5 number of data register */ - __io uint32 CPAR5; /**< Channel 5 peripheral address register */ - __io uint32 CMAR5; /**< Channel 5 memory address register */ - const uint32 RESERVED5; /**< Reserved. */ - __io uint32 CCR6; /**< Channel 6 configuration register */ - __io uint32 CNDTR6; /**< Channel 6 number of data register */ - __io uint32 CPAR6; /**< Channel 6 peripheral address register */ - __io uint32 CMAR6; /**< Channel 6 memory address register */ - const uint32 RESERVED6; /**< Reserved. */ - __io uint32 CCR7; /**< Channel 7 configuration register */ - __io uint32 CNDTR7; /**< Channel 7 number of data register */ - __io uint32 CPAR7; /**< Channel 7 peripheral address register */ - __io uint32 CMAR7; /**< Channel 7 memory address register */ - const uint32 RESERVED7; /**< Reserved. */ -} dma_reg_map; - -/** DMA controller 1 register map base pointer */ -#define DMA1_BASE ((struct dma_reg_map*)0x40020000) - -#ifdef STM32_HIGH_DENSITY -/** DMA controller 2 register map base pointer */ -#define DMA2_BASE ((struct dma_reg_map*)0x40020400) -#endif - -/* - * Register bit definitions - */ - -/* Interrupt status register */ - -#define DMA_ISR_TEIF7_BIT 27 -#define DMA_ISR_HTIF7_BIT 26 -#define DMA_ISR_TCIF7_BIT 25 -#define DMA_ISR_GIF7_BIT 24 -#define DMA_ISR_TEIF6_BIT 23 -#define DMA_ISR_HTIF6_BIT 22 -#define DMA_ISR_TCIF6_BIT 21 -#define DMA_ISR_GIF6_BIT 20 -#define DMA_ISR_TEIF5_BIT 19 -#define DMA_ISR_HTIF5_BIT 18 -#define DMA_ISR_TCIF5_BIT 17 -#define DMA_ISR_GIF5_BIT 16 -#define DMA_ISR_TEIF4_BIT 15 -#define DMA_ISR_HTIF4_BIT 14 -#define DMA_ISR_TCIF4_BIT 13 -#define DMA_ISR_GIF4_BIT 12 -#define DMA_ISR_TEIF3_BIT 11 -#define DMA_ISR_HTIF3_BIT 10 -#define DMA_ISR_TCIF3_BIT 9 -#define DMA_ISR_GIF3_BIT 8 -#define DMA_ISR_TEIF2_BIT 7 -#define DMA_ISR_HTIF2_BIT 6 -#define DMA_ISR_TCIF2_BIT 5 -#define DMA_ISR_GIF2_BIT 4 -#define DMA_ISR_TEIF1_BIT 3 -#define DMA_ISR_HTIF1_BIT 2 -#define DMA_ISR_TCIF1_BIT 1 -#define DMA_ISR_GIF1_BIT 0 - -#define DMA_ISR_TEIF7 BIT(DMA_ISR_TEIF7_BIT) -#define DMA_ISR_HTIF7 BIT(DMA_ISR_HTIF7_BIT) -#define DMA_ISR_TCIF7 BIT(DMA_ISR_TCIF7_BIT) -#define DMA_ISR_GIF7 BIT(DMA_ISR_GIF7_BIT) -#define DMA_ISR_TEIF6 BIT(DMA_ISR_TEIF6_BIT) -#define DMA_ISR_HTIF6 BIT(DMA_ISR_HTIF6_BIT) -#define DMA_ISR_TCIF6 BIT(DMA_ISR_TCIF6_BIT) -#define DMA_ISR_GIF6 BIT(DMA_ISR_GIF6_BIT) -#define DMA_ISR_TEIF5 BIT(DMA_ISR_TEIF5_BIT) -#define DMA_ISR_HTIF5 BIT(DMA_ISR_HTIF5_BIT) -#define DMA_ISR_TCIF5 BIT(DMA_ISR_TCIF5_BIT) -#define DMA_ISR_GIF5 BIT(DMA_ISR_GIF5_BIT) -#define DMA_ISR_TEIF4 BIT(DMA_ISR_TEIF4_BIT) -#define DMA_ISR_HTIF4 BIT(DMA_ISR_HTIF4_BIT) -#define DMA_ISR_TCIF4 BIT(DMA_ISR_TCIF4_BIT) -#define DMA_ISR_GIF4 BIT(DMA_ISR_GIF4_BIT) -#define DMA_ISR_TEIF3 BIT(DMA_ISR_TEIF3_BIT) -#define DMA_ISR_HTIF3 BIT(DMA_ISR_HTIF3_BIT) -#define DMA_ISR_TCIF3 BIT(DMA_ISR_TCIF3_BIT) -#define DMA_ISR_GIF3 BIT(DMA_ISR_GIF3_BIT) -#define DMA_ISR_TEIF2 BIT(DMA_ISR_TEIF2_BIT) -#define DMA_ISR_HTIF2 BIT(DMA_ISR_HTIF2_BIT) -#define DMA_ISR_TCIF2 BIT(DMA_ISR_TCIF2_BIT) -#define DMA_ISR_GIF2 BIT(DMA_ISR_GIF2_BIT) -#define DMA_ISR_TEIF1 BIT(DMA_ISR_TEIF1_BIT) -#define DMA_ISR_HTIF1 BIT(DMA_ISR_HTIF1_BIT) -#define DMA_ISR_TCIF1 BIT(DMA_ISR_TCIF1_BIT) -#define DMA_ISR_GIF1 BIT(DMA_ISR_GIF1_BIT) - -/* Interrupt flag clear register */ - -#define DMA_IFCR_CTEIF7_BIT 27 -#define DMA_IFCR_CHTIF7_BIT 26 -#define DMA_IFCR_CTCIF7_BIT 25 -#define DMA_IFCR_CGIF7_BIT 24 -#define DMA_IFCR_CTEIF6_BIT 23 -#define DMA_IFCR_CHTIF6_BIT 22 -#define DMA_IFCR_CTCIF6_BIT 21 -#define DMA_IFCR_CGIF6_BIT 20 -#define DMA_IFCR_CTEIF5_BIT 19 -#define DMA_IFCR_CHTIF5_BIT 18 -#define DMA_IFCR_CTCIF5_BIT 17 -#define DMA_IFCR_CGIF5_BIT 16 -#define DMA_IFCR_CTEIF4_BIT 15 -#define DMA_IFCR_CHTIF4_BIT 14 -#define DMA_IFCR_CTCIF4_BIT 13 -#define DMA_IFCR_CGIF4_BIT 12 -#define DMA_IFCR_CTEIF3_BIT 11 -#define DMA_IFCR_CHTIF3_BIT 10 -#define DMA_IFCR_CTCIF3_BIT 9 -#define DMA_IFCR_CGIF3_BIT 8 -#define DMA_IFCR_CTEIF2_BIT 7 -#define DMA_IFCR_CHTIF2_BIT 6 -#define DMA_IFCR_CTCIF2_BIT 5 -#define DMA_IFCR_CGIF2_BIT 4 -#define DMA_IFCR_CTEIF1_BIT 3 -#define DMA_IFCR_CHTIF1_BIT 2 -#define DMA_IFCR_CTCIF1_BIT 1 -#define DMA_IFCR_CGIF1_BIT 0 - -#define DMA_IFCR_CTEIF7 BIT(DMA_IFCR_CTEIF7_BIT) -#define DMA_IFCR_CHTIF7 BIT(DMA_IFCR_CHTIF7_BIT) -#define DMA_IFCR_CTCIF7 BIT(DMA_IFCR_CTCIF7_BIT) -#define DMA_IFCR_CGIF7 BIT(DMA_IFCR_CGIF7_BIT) -#define DMA_IFCR_CTEIF6 BIT(DMA_IFCR_CTEIF6_BIT) -#define DMA_IFCR_CHTIF6 BIT(DMA_IFCR_CHTIF6_BIT) -#define DMA_IFCR_CTCIF6 BIT(DMA_IFCR_CTCIF6_BIT) -#define DMA_IFCR_CGIF6 BIT(DMA_IFCR_CGIF6_BIT) -#define DMA_IFCR_CTEIF5 BIT(DMA_IFCR_CTEIF5_BIT) -#define DMA_IFCR_CHTIF5 BIT(DMA_IFCR_CHTIF5_BIT) -#define DMA_IFCR_CTCIF5 BIT(DMA_IFCR_CTCIF5_BIT) -#define DMA_IFCR_CGIF5 BIT(DMA_IFCR_CGIF5_BIT) -#define DMA_IFCR_CTEIF4 BIT(DMA_IFCR_CTEIF4_BIT) -#define DMA_IFCR_CHTIF4 BIT(DMA_IFCR_CHTIF4_BIT) -#define DMA_IFCR_CTCIF4 BIT(DMA_IFCR_CTCIF4_BIT) -#define DMA_IFCR_CGIF4 BIT(DMA_IFCR_CGIF4_BIT) -#define DMA_IFCR_CTEIF3 BIT(DMA_IFCR_CTEIF3_BIT) -#define DMA_IFCR_CHTIF3 BIT(DMA_IFCR_CHTIF3_BIT) -#define DMA_IFCR_CTCIF3 BIT(DMA_IFCR_CTCIF3_BIT) -#define DMA_IFCR_CGIF3 BIT(DMA_IFCR_CGIF3_BIT) -#define DMA_IFCR_CTEIF2 BIT(DMA_IFCR_CTEIF2_BIT) -#define DMA_IFCR_CHTIF2 BIT(DMA_IFCR_CHTIF2_BIT) -#define DMA_IFCR_CTCIF2 BIT(DMA_IFCR_CTCIF2_BIT) -#define DMA_IFCR_CGIF2 BIT(DMA_IFCR_CGIF2_BIT) -#define DMA_IFCR_CTEIF1 BIT(DMA_IFCR_CTEIF1_BIT) -#define DMA_IFCR_CHTIF1 BIT(DMA_IFCR_CHTIF1_BIT) -#define DMA_IFCR_CTCIF1 BIT(DMA_IFCR_CTCIF1_BIT) -#define DMA_IFCR_CGIF1 BIT(DMA_IFCR_CGIF1_BIT) - -/* Channel configuration register */ - -#define DMA_CCR_MEM2MEM_BIT 14 -#define DMA_CCR_MINC_BIT 7 -#define DMA_CCR_PINC_BIT 6 -#define DMA_CCR_CIRC_BIT 5 -#define DMA_CCR_DIR_BIT 4 -#define DMA_CCR_TEIE_BIT 3 -#define DMA_CCR_HTIE_BIT 2 -#define DMA_CCR_TCIE_BIT 1 -#define DMA_CCR_EN_BIT 0 - -#define DMA_CCR_MEM2MEM BIT(DMA_CCR_MEM2MEM_BIT) -#define DMA_CCR_PL (0x3 << 12) -#define DMA_CCR_PL_LOW (0x0 << 12) -#define DMA_CCR_PL_MEDIUM (0x1 << 12) -#define DMA_CCR_PL_HIGH (0x2 << 12) -#define DMA_CCR_PL_VERY_HIGH (0x3 << 12) -#define DMA_CCR_MSIZE (0x3 << 10) -#define DMA_CCR_MSIZE_8BITS (0x0 << 10) -#define DMA_CCR_MSIZE_16BITS (0x1 << 10) -#define DMA_CCR_MSIZE_32BITS (0x2 << 10) -#define DMA_CCR_PSIZE (0x3 << 8) -#define DMA_CCR_PSIZE_8BITS (0x0 << 8) -#define DMA_CCR_PSIZE_16BITS (0x1 << 8) -#define DMA_CCR_PSIZE_32BITS (0x2 << 8) -#define DMA_CCR_MINC BIT(DMA_CCR_MINC_BIT) -#define DMA_CCR_PINC BIT(DMA_CCR_PINC_BIT) -#define DMA_CCR_CIRC BIT(DMA_CCR_CIRC_BIT) -#define DMA_CCR_DIR BIT(DMA_CCR_DIR_BIT) -#define DMA_CCR_TEIE BIT(DMA_CCR_TEIE_BIT) -#define DMA_CCR_HTIE BIT(DMA_CCR_HTIE_BIT) -#define DMA_CCR_TCIE BIT(DMA_CCR_TCIE_BIT) -#define DMA_CCR_EN BIT(DMA_CCR_EN_BIT) - -/* - * Devices - */ - -/** Encapsulates state related to a DMA channel interrupt. */ -typedef struct dma_handler_config { - void (*handler)(void); /**< User-specified channel interrupt - handler */ - nvic_irq_num irq_line; /**< Channel's NVIC interrupt number */ -} dma_handler_config; - -/** DMA device type */ -typedef struct dma_dev { - dma_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< Clock ID */ - dma_handler_config handlers[]; /**< - * @brief IRQ handlers and NVIC numbers. - * - * @see dma_attach_interrupt() - * @see dma_detach_interrupt() - */ -} dma_dev; - -extern dma_dev *DMA1; -#ifdef STM32_HIGH_DENSITY -extern dma_dev *DMA2; -#endif - -/* - * Convenience functions - */ - -void dma_init(dma_dev *dev); - -/** Flags for DMA transfer configuration. */ -typedef enum dma_mode_flags { - DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */ - DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */ - DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */ - DMA_CIRC_MODE = 1 << 5, /**< Circular mode */ - DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */ - DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */ - DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */ - DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */ -} dma_mode_flags; - -/** Source and destination transfer sizes. */ -typedef enum dma_xfer_size { - DMA_SIZE_8BITS = 0, /**< 8-bit transfers */ - DMA_SIZE_16BITS = 1, /**< 16-bit transfers */ - DMA_SIZE_32BITS = 2 /**< 32-bit transfers */ -} dma_xfer_size; - -/** DMA channel */ -typedef enum dma_channel { - DMA_CH1 = 1, /**< Channel 1 */ - DMA_CH2 = 2, /**< Channel 2 */ - DMA_CH3 = 3, /**< Channel 3 */ - DMA_CH4 = 4, /**< Channel 4 */ - DMA_CH5 = 5, /**< Channel 5 */ - DMA_CH6 = 6, /**< Channel 6 */ - DMA_CH7 = 7, /**< Channel 7 */ -} dma_channel; - -void dma_setup_transfer(dma_dev *dev, - dma_channel channel, - __io void *peripheral_address, - dma_xfer_size peripheral_size, - __io void *memory_address, - dma_xfer_size memory_size, - uint32 mode); - -void dma_set_num_transfers(dma_dev *dev, - dma_channel channel, - uint16 num_transfers); - -/** DMA transfer priority. */ -typedef enum dma_priority { - DMA_PRIORITY_LOW = DMA_CCR_PL_LOW, /**< Low priority */ - DMA_PRIORITY_MEDIUM = DMA_CCR_PL_MEDIUM, /**< Medium priority */ - DMA_PRIORITY_HIGH = DMA_CCR_PL_HIGH, /**< High priority */ - DMA_PRIORITY_VERY_HIGH = DMA_CCR_PL_VERY_HIGH /**< Very high priority */ -} dma_priority; - -void dma_set_priority(dma_dev *dev, - dma_channel channel, - dma_priority priority); - -void dma_attach_interrupt(dma_dev *dev, - dma_channel channel, - void (*handler)(void)); -void dma_detach_interrupt(dma_dev *dev, dma_channel channel); - -/** - * Encodes the reason why a DMA interrupt was called. - * @see dma_get_irq_cause() - */ -typedef enum dma_irq_cause { - DMA_TRANSFER_COMPLETE, /**< Transfer is complete. */ - DMA_TRANSFER_HALF_COMPLETE, /**< Transfer is half complete. */ - DMA_TRANSFER_ERROR, /**< Error occurred during transfer. */ -} dma_irq_cause; - -dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel); - -void dma_enable(dma_dev *dev, dma_channel channel); -void dma_disable(dma_dev *dev, dma_channel channel); - -void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *address); -void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *address); - -/** - * @brief DMA channel register map type. - * - * Provides access to an individual channel's registers. - */ -typedef struct dma_channel_reg_map { - __io uint32 CCR; /**< Channel configuration register */ - __io uint32 CNDTR; /**< Channel number of data register */ - __io uint32 CPAR; /**< Channel peripheral address register */ - __io uint32 CMAR; /**< Channel memory address register */ -} dma_channel_reg_map; - -#define DMA_CHANNEL_NREGS 5 - -/** - * @brief Obtain a pointer to an individual DMA channel's registers. - * - * For example, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1. - * - * @param dev DMA device - * @param channel DMA channel whose channel register map to obtain. - */ -static inline dma_channel_reg_map* dma_channel_regs(dma_dev *dev, - dma_channel channel) { - __io uint32 *ccr1 = &dev->regs->CCR1; - return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (channel - 1)); -} - -/** - * @brief Check if a DMA channel is enabled - * @param dev DMA device - * @param channel Channel whose enabled bit to check. - */ -static inline uint8 dma_is_channel_enabled(dma_dev *dev, dma_channel channel) { - return (uint8)(dma_channel_regs(dev, channel)->CCR & DMA_CCR_EN); -} - -/** - * @brief Get the ISR status bits for a DMA channel. - * - * The bits are returned right-aligned, in the following order: - * transfer error flag, half-transfer flag, transfer complete flag, - * global interrupt flag. - * - * If you're attempting to figure out why a DMA interrupt fired; you - * may find dma_get_irq_cause() more convenient. - * - * @param dev DMA device - * @param channel Channel whose ISR bits to return. - * @see dma_get_irq_cause(). - */ -static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_channel channel) { - uint8 shift = (channel - 1) * 4; - return (dev->regs->ISR >> shift) & 0xF; -} - -/** - * @brief Clear the ISR status bits for a given DMA channel. - * - * If you're attempting to clean up after yourself in a DMA interrupt, - * you may find dma_get_irq_cause() more convenient. - * - * @param dev DMA device - * @param channel Channel whose ISR bits to clear. - * @see dma_get_irq_cause() - */ -static inline void dma_clear_isr_bits(dma_dev *dev, dma_channel channel) { - dev->regs->IFCR = BIT(4 * (channel - 1)); -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F4/cores/maple/libmaple/dmaF2.c b/STM32F4/cores/maple/libmaple/dmaF4.c similarity index 90% rename from STM32F4/cores/maple/libmaple/dmaF2.c rename to STM32F4/cores/maple/libmaple/dmaF4.c index 0911e58..173f3a2 100644 --- a/STM32F4/cores/maple/libmaple/dmaF2.c +++ b/STM32F4/cores/maple/libmaple/dmaF4.c @@ -24,10 +24,10 @@ * SOFTWARE. *****************************************************************************/ - #ifdef STM32F2 +#ifdef STM32F4 /** - * @file dmaF2.c + * @file dmaF4.c * @brief Direct Memory Access peripheral support */ @@ -117,33 +117,16 @@ void dma_detach_interrupt(dma_dev *dev, dma_stream stream) { dev->handlers[stream].handler = NULL; } -void dma_clear_isr_bits(dma_dev *dev, dma_stream stream) { - switch (stream) { - case 0: - dev->regs->LIFCR|=0x0000003d; - break; - case 1: - dev->regs->LIFCR|=0x00000f40; - break; - case 2: - dev->regs->LIFCR|=0x003d0000; - break; - case 3: - dev->regs->LIFCR|=0x0f400000; - break; - case 4: - dev->regs->HIFCR|=0x0000003d; - break; - case 5: - dev->regs->HIFCR|=0x00000f40; - break; - case 6: - dev->regs->HIFCR|=0x003d0000; - break; - case 7: - dev->regs->HIFCR|=0x0f400000; - break; - } +const uint8 dma_isr_bits_shift[] = { 0, 6, 16, 22}; + +uint8 dma_get_isr_bit(dma_dev *dev, dma_stream stream, uint8_t mask) { + if ( stream&0xFC ) return ((dev->regs->HISR)>>dma_isr_bits_shift[stream&0x03]) & mask; + else return ((dev->regs->LISR)>>dma_isr_bits_shift[stream&0x03]) & mask; +} + +void dma_clear_isr_bit(dma_dev *dev, dma_stream stream, uint8_t mask) { + if ( stream&0xFC ) dev->regs->HIFCR = (uint32)mask << dma_isr_bits_shift[stream&0x03]; + else dev->regs->LIFCR = (uint32)mask << dma_isr_bits_shift[stream&0x03]; } /* diff --git a/STM32F4/cores/maple/libmaple/dmaF2.h b/STM32F4/cores/maple/libmaple/dmaF4.h similarity index 52% rename from STM32F4/cores/maple/libmaple/dmaF2.h rename to STM32F4/cores/maple/libmaple/dmaF4.h index 6f7086f..388c64b 100644 --- a/STM32F4/cores/maple/libmaple/dmaF2.h +++ b/STM32F4/cores/maple/libmaple/dmaF4.h @@ -25,7 +25,7 @@ *****************************************************************************/ /** - * @file dma.h + * @file dmaF4.h * * @author Marti Bolivar ; * Original implementation by Michael Hope @@ -57,35 +57,35 @@ extern "C"{ * */ typedef struct dma_stream_t { - __io uint32 CR; /**< Stream configuration register */ - __io uint32 NDTR; /**< Stream number of data register */ - __io uint32 PAR; /**< Stream peripheral address register */ - __io uint32 M0AR; /**< Stream memory address register 0 */ - __io uint32 M1AR; /**< Stream memory address register 1 */ - __io uint32 FCR; /**< Stream FIFO configuration register */ + __IO uint32 CR; /**< Stream configuration register */ + __IO uint32 NDTR; /**< Stream number of data register */ + __IO uint32 PAR; /**< Stream peripheral address register */ + __IO uint32 M0AR; /**< Stream memory address register 0 */ + __IO uint32 M1AR; /**< Stream memory address register 1 */ + __IO uint32 FCR; /**< Stream FIFO configuration register */ } dma_stream_t; /** * @brief DMA register map type. * */ typedef struct dma_reg_map { - __io uint32 LISR; /**< Low interrupt status register */ - __io uint32 HISR; /**< High interrupt status register */ - __io uint32 LIFCR; /**< Low interrupt flag clear register */ - __io uint32 HIFCR; /**< High interrupt flag clear register */ - dma_stream_t STREAM[8]; + __IO uint32 LISR; /**< Low interrupt status register */ + __IO uint32 HISR; /**< High interrupt status register */ + __IO uint32 LIFCR; /**< Low interrupt flag clear register */ + __IO uint32 HIFCR; /**< High interrupt flag clear register */ + dma_stream_t STREAM[8]; } dma_reg_map; /** DMA controller register map base pointers */ #define DMA1_BASE ((struct dma_reg_map*)0x40026000) #define DMA2_BASE ((struct dma_reg_map*)0x40026400) + /* * Register bit definitions */ -/* Channel configuration register */ - +// Stream configuration register #define DMA_CR_CH0 (0x0 << 25) #define DMA_CR_CH1 (0x1 << 25) #define DMA_CR_CH2 (0x2 << 25) @@ -134,11 +134,45 @@ typedef struct dma_reg_map { #define DMA_CR_HTIE (0x1 << 3) #define DMA_CR_TEIE (0x1 << 2) #define DMA_CR_DMEIE (0x1 << 1) -#define DMA_CR_EN (0x1) +#define DMA_CR_EN (0x1 << 0) -/* - * Devices - */ +// Device interrupt status register flags +#define DMA_ISR_TCIF (1 << 5) +#define DMA_ISR_HTIF (1 << 4) +#define DMA_ISR_TEIF (1 << 3) +#define DMA_ISR_DMEIF (1 << 2) +#define DMA_ISR_FEIF (1 << 0) + +#define DMA_ISR_ERROR_BITS (DMA_ISR_TEIF | DMA_ISR_DMEIF | DMA_ISR_FEIF) +#define DMA_ISR_BIT_MASK 0x3D + +// FIFO control register flags +#define DMA_FCR_FEIE (0x1 << 7) // FIFO error interrupt enable +#define DMA_FCR_FS (0x7 << 3) // FIFO status (READ_ONLY): +#define DMA_FCR_FS_LEVEL_1 (0x0 << 3) // 000: 0 < fifo_level < 1/4 +#define DMA_FCR_FS_LEVEL_2 (0x1 << 3) // 001: 1/4 ≤ fifo_level < 1/2 +#define DMA_FCR_FS_LEVEL_3 (0x2 << 3) // 010: 1/2 ≤ fifo_level < 3/4 +#define DMA_FCR_FS_LEVEL_4 (0x3 << 3) // 011: 3/4 ≤ fifo_level < full +#define DMA_FCR_FS_EMPTY (0x4 << 3) // 100: FIFO is empty +#define DMA_FCR_FS_FULL (0x5 << 3) // 101: FIFO is full +#define DMA_FCR_DMDIS (0x1 << 2) // Direct mode disable +#define DMA_FCR_FTH (0x3 << 0) // FIFO threshold selection +#define DMA_FCR_FTH_1_4 (0x0 << 0) // 1/4 full FIFO +#define DMA_FCR_FTH_2_4 (0x1 << 0) // 2/4 full FIFO +#define DMA_FCR_FTH_3_4 (0x2 << 0) // 3/4 full FIFO +#define DMA_FCR_FTH_FULL (0x3 << 0) // full FIFO + + +typedef enum dma_channel { + DMA_CH0 = DMA_CR_CH0, /**< Channel 0 */ + DMA_CH1 = DMA_CR_CH1, /**< Channel 1 */ + DMA_CH2 = DMA_CR_CH2, /**< Channel 2 */ + DMA_CH3 = DMA_CR_CH3, /**< Channel 3 */ + DMA_CH4 = DMA_CR_CH4, /**< Channel 4 */ + DMA_CH5 = DMA_CR_CH5, /**< Channel 5 */ + DMA_CH6 = DMA_CR_CH6, /**< Channel 6 */ + DMA_CH7 = DMA_CR_CH7, /**< Channel 7 */ +} dma_channel; /** Encapsulates state related to a DMA channel interrupt. */ typedef struct dma_handler_config { @@ -153,40 +187,53 @@ typedef struct dma_dev { rcc_clk_id clk_id; /**< Clock ID */ dma_handler_config handlers[]; /**< * @brief IRQ handlers and NVIC numbers. - * - * @see dma_attach_interrupt() * @see dma_detach_interrupt() */ } dma_dev; +/* + * Devices + */ extern dma_dev *DMA1; extern dma_dev *DMA2; -/* - * Convenience functions - */ - -void dma_init(dma_dev *dev); - /** Flags for DMA transfer configuration. */ typedef enum dma_mode_flags { - DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */ - DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */ - DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */ - DMA_CIRC_MODE = 1 << 5, /**< Circular mode */ - DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */ - DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */ - DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */ - DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */ + DMA_MEM_BUF_0 = DMA_CR_CT0, /**< Current memory target buffer 0 */ + DMA_MEM_BUF_1 = DMA_CR_CT1, /**< Current memory target buffer 1 */ + DMA_DBL_BUF_MODE = DMA_CR_DBM, /**< Current memory double buffer mode */ + DMA_PINC_OFFSET = DMA_CR_PINCOS, /**< Peripheral increment offset size */ + DMA_MINC_MODE = DMA_CR_MINC, /**< Memory increment mode */ + DMA_PINC_MODE = DMA_CR_PINC, /**< Peripheral increment mode */ + DMA_CIRC_MODE = DMA_CR_CIRC, /**< Memory Circular mode */ + DMA_FROM_PER = DMA_CR_DIR_P2M, /**< Read from memory to peripheral */ + DMA_FROM_MEM = DMA_CR_DIR_M2P, /**< Read from memory to peripheral */ + DMA_MEM_TO_MEM = DMA_CR_DIR_M2M, /**< Read from memory to memory */ + DMA_PERIF_CTRL = DMA_CR_PFCTRL, /**< Peripheral flow controller */ + DMA_PRIO_MEDIUM = DMA_CR_PL_MEDIUM, /**< Medium priority */ + DMA_PRIO_HIGH = DMA_CR_PL_HIGH, /**< High priority */ + DMA_PRIO_VERY_HIGH = DMA_CR_PL_VERY_HIGH, /**< Very high priority */ + DMA_TRNS_CMPLT = DMA_CR_TCIE, /**< Interrupt on transfer completion */ + DMA_TRNS_HALF = DMA_CR_HTIE, /**< Interrupt on half-transfer */ + DMA_TRNS_ERR = DMA_CR_TEIE, /**< Interrupt on transfer error */ + DMA_DIR_MODE_ERR = DMA_CR_DMEIE /**< Interrupt on direct mode error */ } dma_mode_flags; -/** Source and destination transfer sizes. */ +// Source and destination transfer sizes. typedef enum dma_xfer_size { - DMA_SIZE_8BITS = 0, /**< 8-bit transfers */ - DMA_SIZE_16BITS = 1, /**< 16-bit transfers */ - DMA_SIZE_32BITS = 2 /**< 32-bit transfers */ + DMA_SIZE_8BITS = ( DMA_CR_MSIZE_8BITS|DMA_CR_PSIZE_8BITS ), // 8-bit transfers + DMA_SIZE_16BITS = (DMA_CR_MSIZE_16BITS|DMA_CR_PSIZE_16BITS), // 16-bit transfers + DMA_SIZE_32BITS = (DMA_CR_MSIZE_32BITS|DMA_CR_PSIZE_32BITS) // 32-bit transfers } dma_xfer_size; +// Source and destination burst sizes. +typedef enum dma_burst_size { + DMA_BURST_INCR0 = ( DMA_CR_MBURST0|DMA_CR_PBURST0 ), // single transfer + DMA_BURST_INCR4 = ( DMA_CR_MBURST4|DMA_CR_PBURST4 ), // incremental burst of 4 beats + DMA_BURST_INCR8 = ( DMA_CR_MBURST8|DMA_CR_PBURST8 ), // incremental burst of 8 beats + DMA_BURST_INCR16 = (DMA_CR_MBURST16|DMA_CR_PBURST16) // incremental burst of 16 beats +} dma_burst_size; + /** DMA channel */ typedef enum dma_stream { DMA_STREAM0 = 0, /**< Stream 0 */ @@ -198,26 +245,37 @@ typedef enum dma_stream { DMA_STREAM6 = 6, /**< Stream 6 */ DMA_STREAM7 = 7, /**< Stream 7 */ } dma_stream; - + +/* + * Convenience functions + */ +extern void dma_init(dma_dev *dev); + static inline void dma_setup_transfer(dma_dev *dev, dma_stream stream, - __io void *peripheral_address, - __io void *memory_address0, - __io void *memory_address1, - uint32 flags, - uint32 fifo_flags) { + dma_channel channel, + dma_xfer_size trx_size, + __IO void *peripheral_address, + __IO void *memory_address0, + __IO void *memory_address1, + uint32 flags) +{ dev->regs->STREAM[stream].CR &= ~DMA_CR_EN; // disable + while( (dev->regs->STREAM[stream].CR)&DMA_CR_EN ); // wait till enable bit is cleared dev->regs->STREAM[stream].PAR = (uint32)peripheral_address; dev->regs->STREAM[stream].M0AR = (uint32)memory_address0; dev->regs->STREAM[stream].M1AR = (uint32)memory_address1; - dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits - dev->regs->STREAM[stream].CR = flags & 0x0feffffe; // mask out reserved and enable + dev->regs->STREAM[stream].CR = (uint32)((flags|channel|trx_size) & 0x0feffffe); // mask out reserved and enable } -static inline void dma_set_num_transfers(dma_dev *dev, - dma_stream stream, - uint16 num_transfers) { - dev->regs->STREAM[stream].NDTR = num_transfers; +static inline void dma_set_num_transfers(dma_dev *dev, dma_stream stream, uint16 num_transfers) +{ + dev->regs->STREAM[stream].NDTR = (uint32)num_transfers; +} + +static inline void dma_set_fifo_flags(dma_dev *dev, dma_stream stream, uint8 fifo_flags) +{ + dev->regs->STREAM[stream].FCR = (uint32)(fifo_flags & 0x87); // mask out reserved bits } void dma_attach_interrupt(dma_dev *dev, @@ -226,12 +284,15 @@ void dma_attach_interrupt(dma_dev *dev, void dma_detach_interrupt(dma_dev *dev, dma_stream stream); -static inline void dma_enable(dma_dev *dev, dma_stream stream) { - dev->regs->STREAM[stream].CR |= DMA_CR_EN; +static inline void dma_enable(dma_dev *dev, dma_stream stream) +{ + dev->regs->STREAM[stream].CR |= (uint32)DMA_CR_EN; } -static inline void dma_disable(dma_dev *dev, dma_stream stream) { - dev->regs->STREAM[stream].CR &= ~DMA_CR_EN; +static inline void dma_disable(dma_dev *dev, dma_stream stream) +{ + dev->regs->STREAM[stream].CR &= (uint32)(~DMA_CR_EN); + while (dev->regs->STREAM[stream].CR & DMA_CR_EN); // wait till EN bit is reset, see AN4031, chapter 4.1 } /** @@ -253,7 +314,11 @@ static inline uint8 dma_is_stream_enabled(dma_dev *dev, dma_stream stream) { * @param dev DMA device * @param stream Stream whose ISR bits to return. */ -uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream); +uint8 dma_get_isr_bit(dma_dev *dev, dma_stream stream, uint8_t mask); + +static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream) { + return dma_get_isr_bit(dev, stream, DMA_ISR_BIT_MASK); +} /** * @brief Clear the ISR status bits for a given DMA stream. @@ -261,7 +326,11 @@ uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream); * @param dev DMA device * @param stream Stream whose ISR bits to clear. */ -void dma_clear_isr_bits(dma_dev *dev, dma_stream stream); +void dma_clear_isr_bit(dma_dev *dev, dma_stream stream, uint8_t mask); + +static inline void dma_clear_isr_bits(dma_dev *dev, dma_stream stream) { + dma_clear_isr_bit(dev, stream, DMA_ISR_BIT_MASK); +} #ifdef __cplusplus } // extern "C" diff --git a/STM32F4/cores/maple/libmaple/exti.h b/STM32F4/cores/maple/libmaple/exti.h index bac8adc..83a3cc2 100644 --- a/STM32F4/cores/maple/libmaple/exti.h +++ b/STM32F4/cores/maple/libmaple/exti.h @@ -43,20 +43,16 @@ extern "C"{ /** EXTI register map type */ typedef struct exti_reg_map { - __io uint32 IMR; /**< Interrupt mask register */ - __io uint32 EMR; /**< Event mask register */ - __io uint32 RTSR; /**< Rising trigger selection register */ - __io uint32 FTSR; /**< Falling trigger selection register */ - __io uint32 SWIER; /**< Software interrupt event register */ - __io uint32 PR; /**< Pending register */ + __IO uint32 IMR; /**< Interrupt mask register */ + __IO uint32 EMR; /**< Event mask register */ + __IO uint32 RTSR; /**< Rising trigger selection register */ + __IO uint32 FTSR; /**< Falling trigger selection register */ + __IO uint32 SWIER; /**< Software interrupt event register */ + __IO uint32 PR; /**< Pending register */ } exti_reg_map; /** EXTI register map base pointer */ -#ifdef STM32F2 #define EXTI_BASE ((struct exti_reg_map*)0x40013C00) -#else -#define EXTI_BASE ((struct exti_reg_map*)0x40010400) -#endif /** External interrupt trigger mode */ typedef enum exti_trigger_mode { diff --git a/STM32F4/cores/maple/libmaple/flash.h b/STM32F4/cores/maple/libmaple/flash.h index 0b4e49b..d9730ca 100644 --- a/STM32F4/cores/maple/libmaple/flash.h +++ b/STM32F4/cores/maple/libmaple/flash.h @@ -41,14 +41,14 @@ extern "C"{ /** Flash register map type */ typedef struct flash_reg_map { - __io uint32 ACR; /**< Access control register */ - __io uint32 KEYR; /**< Key register */ - __io uint32 OPTKEYR; /**< OPTKEY register */ - __io uint32 SR; /**< Status register */ - __io uint32 CR; /**< Control register */ - __io uint32 AR; /**< Address register */ - __io uint32 OBR; /**< Option byte register */ - __io uint32 WRPR; /**< Write protection register */ + __IO uint32 ACR; /**< Access control register */ + __IO uint32 KEYR; /**< Key register */ + __IO uint32 OPTKEYR; /**< OPTKEY register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 CR; /**< Control register */ + __IO uint32 AR; /**< Address register */ + __IO uint32 OBR; /**< Option byte register */ + __IO uint32 WRPR; /**< Write protection register */ } flash_reg_map; /** Flash register map base pointer */ diff --git a/STM32F4/cores/maple/libmaple/fsmc.c b/STM32F4/cores/maple/libmaple/fsmc.c index 06ca7df..1e3691a 100644 --- a/STM32F4/cores/maple/libmaple/fsmc.c +++ b/STM32F4/cores/maple/libmaple/fsmc.c @@ -32,62 +32,56 @@ #include "fsmc.h" #include "gpio.h" -#ifdef STM32_HIGH_DENSITY +#if defined(STM32_HIGH_DENSITY) && defined(BOARD_generic_f407v) // pins not yet defined for disco F407 /** - * Configure FSMC GPIOs for use with SRAM. + * Configure FSMC GPIOs for use with LCDs. */ -void fsmc_sram_init_gpios(void) { - /* Data lines... */ - gpio_set_mode(GPIOD, 0, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 1, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 8, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 9, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 10, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 14, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 15, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 7, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 8, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 9, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 10, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 11, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 12, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 13, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 14, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOE, 15, GPIO_AF_OUTPUT_PP); - /* Address lines... */ - gpio_set_mode(GPIOD, 11, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 12, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOD, 13, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 0, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 1, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 2, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 3, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 4, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 5, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 12, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 13, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 14, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOF, 15, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOG, 0, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOG, 1, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOG, 2, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOG, 3, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOG, 4, GPIO_AF_OUTPUT_PP); - gpio_set_mode(GPIOG, 5, GPIO_AF_OUTPUT_PP); - - /* And control lines... */ - gpio_set_mode(GPIOD, 4, GPIO_AF_OUTPUT_PP); // NOE - gpio_set_mode(GPIOD, 5, GPIO_AF_OUTPUT_PP); // NWE - - gpio_set_mode(GPIOD, 7, GPIO_AF_OUTPUT_PP); // NE1 - gpio_set_mode(GPIOG, 9, GPIO_AF_OUTPUT_PP); // NE2 - gpio_set_mode(GPIOG, 10, GPIO_AF_OUTPUT_PP); // NE3 - gpio_set_mode(GPIOG, 12, GPIO_AF_OUTPUT_PP); // NE4 - - gpio_set_mode(GPIOE, 0, GPIO_AF_OUTPUT_PP); // NBL0 - gpio_set_mode(GPIOE, 1, GPIO_AF_OUTPUT_PP); // NBL1 +void fsmc_init(void) { + rcc_clk_enable(RCC_FSMC); + rcc_reset_dev(RCC_FSMC); } +// used control, address and data lines +// NOE -> RD, NWE -> WR, A18 -> RS, NE1 -> CS +const uint8_t fsmc_pins[]= {FSMC_NOE, FSMC_NWE, FSMC_NE1, FSMC_A18, + FSMC_D0, FSMC_D1, FSMC_D2, FSMC_D3, + FSMC_D4, FSMC_D5, FSMC_D6, FSMC_D7, + FSMC_D8, FSMC_D9, FSMC_D10, FSMC_D11, + FSMC_D12, FSMC_D13, FSMC_D14, FSMC_D15}; + +void fsmc_lcd_init_gpios(void) { + uint8_t i; + for (i=0; i +#include "libmaple_types.h" + #ifdef __cplusplus extern "C"{ #endif @@ -54,42 +55,42 @@ extern "C"{ /** FSMC register map type */ typedef struct fsmc_reg_map { - __io uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ - __io uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ - __io uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ - __io uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ - __io uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ - __io uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ - __io uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ - __io uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ - const uint8 RESERVED1[64]; /**< Reserved */ - __io uint32 PCR2; /**< PC Card/NAND Flash control register 2 */ - __io uint32 SR2; /**< FIFO status and interrupt register 2 */ - __io uint32 PMEM2; /**< Common memory space timing register 2 */ - __io uint32 PATT2; /**< Attribute memory space timing register 2 */ - const uint8 RESERVED2[4]; /**< Reserved */ - __io uint32 ECCR2; /**< ECC result register 2 */ - const uint8 RESERVED3[2]; - __io uint32 PCR3; /**< PC Card/NAND Flash control register 3 */ - __io uint32 SR3; /**< FIFO status and interrupt register 3 */ - __io uint32 PMEM3; /**< Common memory space timing register 3 */ - __io uint32 PATT3; /**< Attribute memory space timing register 3 */ + __IO uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ + __IO uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ + __IO uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ + __IO uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ + __IO uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ + __IO uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ + __IO uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ + __IO uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ + const uint32 RESERVED1[16]; /**< Reserved */ + __IO uint32 PCR2; /**< PC Card/NAND Flash control register 2 */ + __IO uint32 SR2; /**< FIFO status and interrupt register 2 */ + __IO uint32 PMEM2; /**< Common memory space timing register 2 */ + __IO uint32 PATT2; /**< Attribute memory space timing register 2 */ + const uint32 RESERVED2; /**< Reserved */ + __IO uint32 ECCR2; /**< ECC result register 2 */ + const uint32 RESERVED3[2]; /**< Reserved */ + __IO uint32 PCR3; /**< PC Card/NAND Flash control register 3 */ + __IO uint32 SR3; /**< FIFO status and interrupt register 3 */ + __IO uint32 PMEM3; /**< Common memory space timing register 3 */ + __IO uint32 PATT3; /**< Attribute memory space timing register 3 */ const uint32 RESERVED4; /**< Reserved */ - __io uint32 ECCR3; /**< ECC result register 3 */ - const uint8 RESERVED5[8]; /**< Reserved */ - __io uint32 PCR4; /**< PC Card/NAND Flash control register 4 */ - __io uint32 SR4; /**< FIFO status and interrupt register 4 */ - __io uint32 PMEM4; /**< Common memory space timing register 4 */ - __io uint32 PATT4; /**< Attribute memory space timing register 4 */ - __io uint32 PIO4; /**< I/O space timing register 4 */ - const uint8 RESERVED6[80]; /**< Reserved */ - __io uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ + __IO uint32 ECCR3; /**< ECC result register 3 */ + const uint32 RESERVED5[2]; /**< Reserved */ + __IO uint32 PCR4; /**< PC Card/NAND Flash control register 4 */ + __IO uint32 SR4; /**< FIFO status and interrupt register 4 */ + __IO uint32 PMEM4; /**< Common memory space timing register 4 */ + __IO uint32 PATT4; /**< Attribute memory space timing register 4 */ + __IO uint32 PIO4; /**< I/O space timing register 4 */ + const uint32 RESERVED6[20]; /**< Reserved */ + __IO uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ const uint32 RESERVED7; /**< Reserved */ - __io uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ + __IO uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ const uint32 RESERVED8; /**< Reserved */ - __io uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ + __IO uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ const uint32 RESERVED9; /**< Reserved */ - __io uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ + __IO uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ } __attribute__((packed)) fsmc_reg_map; #define __FSMCB 0xA0000000 @@ -99,10 +100,10 @@ typedef struct fsmc_reg_map { /** FSMC NOR/PSRAM register map type */ typedef struct fsmc_nor_psram_reg_map { - __io uint32 BCR; /**< Chip-select control register */ - __io uint32 BTR; /**< Chip-select timing register */ - const uint8 RESERVED[252]; /**< Reserved */ - __io uint32 BWTR; /**< Write timing register */ + __IO uint32 BCR; /**< Chip-select control register */ + __IO uint32 BTR; /**< Chip-select timing register */ + const uint32 RESERVED[63]; /**< Reserved */ + __IO uint32 BWTR; /**< Write timing register */ } fsmc_nor_psram_reg_map; /** FSMC NOR/PSRAM base pointer 1 */ @@ -170,6 +171,13 @@ typedef struct fsmc_nor_psram_reg_map { #define FSMC_BTR_ADDHLD (0xF << 4) #define FSMC_BTR_ADDSET 0xF +#define FSMC_BTR_DATLAT_(x) ((x<<24)&FSMC_BTR_DATLAT) +#define FSMC_BTR_CLKDIV_(x) ((x<<20)&FSMC_BTR_CLKDIV) +#define FSMC_BTR_BUSTURN_(x) ((x<<16)&FSMC_BTR_BUSTURN) +#define FSMC_BTR_DATAST_(x) ((x<<8)&FSMC_BTR_DATAST) +#define FSMC_BTR_ADDHLD_(x) ((x<<4)&FSMC_BTR_ADDHLD) +#define FSMC_BTR_ADDSET_(x) ((x<<0)&FSMC_BTR_ADDSET) + /* SRAM/NOR-Flash write timing registers */ #define FSMC_BWTR_ACCMOD (0x3 << 28) @@ -280,8 +288,26 @@ typedef struct fsmc_nor_psram_reg_map { /* * SRAM/NOR Flash routines */ +extern volatile uint16_t * fsmcData; +extern volatile uint16_t * fsmcCommand; -void fsmc_sram_init_gpios(void); +void fsmc_lcd_init(void); + +static inline void fsmc_nor_psram_set_BCR(fsmc_nor_psram_reg_map *regs, uint32_t bcr) { + regs->BCR = bcr; +} + +static inline void fsmc_nor_psram_set_BTR(fsmc_nor_psram_reg_map *regs, uint32_t btr) { + regs->BTR = btr; +} + +static inline void fsmc_nor_psram_bank_enable(fsmc_nor_psram_reg_map *regs) { + regs->BCR |= FSMC_BCR_MBKEN; +} + +static inline void fsmc_nor_psram_bank_disable(fsmc_nor_psram_reg_map *regs) { + regs->BCR ^= FSMC_BCR_MBKEN; +} /** * Set the DATAST bits in the given NOR/PSRAM register map's diff --git a/STM32F4/cores/maple/libmaple/gpio.c b/STM32F4/cores/maple/libmaple/gpio.c deleted file mode 100644 index 3792220..0000000 --- a/STM32F4/cores/maple/libmaple/gpio.c +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file gpio.c - * @brief GPIO initialization routine - */ - -// #ifdef STM32F2 -// #include "gpioF2.c" -// #else -// #include "gpioF1.c" -// #endif diff --git a/STM32F4/cores/maple/libmaple/gpio.h b/STM32F4/cores/maple/libmaple/gpio.h index 4d42386..79ce7d3 100644 --- a/STM32F4/cores/maple/libmaple/gpio.h +++ b/STM32F4/cores/maple/libmaple/gpio.h @@ -31,8 +31,102 @@ * (AFIO) prototypes, defines, and inlined access functions. */ -#ifdef STM32F2 -#include "gpioF2.h" -#else -#include "gpioF1.h" +#ifndef _GPIO_H_ +#define _GPIO_H_ + +#include "libmaple.h" +#include "boards.h" + +#ifdef __cplusplus +extern "C"{ #endif + + +/** + * @brief Get a GPIO port's corresponding afio_exti_port. + * @param dev GPIO device whose afio_exti_port to return. + */ +static inline afio_exti_port gpio_exti_port(const gpio_dev *dev) { + return dev->exti_port; +} + +/** + * Set or reset a GPIO pin. + * + * Pin must have previously been configured to output mode. + * + * @param dev GPIO device whose pin to set. + * @param pin Pin on to set or reset + * @param val If true, set the pin. If false, reset the pin. + */ +static inline void gpio_write_pin(uint8_t pin, uint8 val) { + if (val) { + (PIN_MAP[pin].gpio_device)->regs->BSRRL = BIT(pin&0x0F); + } else { + (PIN_MAP[pin].gpio_device)->regs->BSRRH = BIT(pin&0x0F); + } +} + +static inline void gpio_set_pin(uint8_t pin) { + (PIN_MAP[pin].gpio_device)->regs->BSRRL = BIT(pin&0x0F); +} + +static inline void gpio_clear_pin(uint8_t pin) { + (PIN_MAP[pin].gpio_device)->regs->BSRRH = BIT(pin&0x0F); +} + +/** + * Determine whether or not a GPIO pin is set. + * + * Pin must have previously been configured to input mode. + * + * @param dev GPIO device whose pin to test. + * @param pin Pin on dev to test. + * @return True if the pin is set, false otherwise. + */ +static inline uint32 gpio_read_pin(uint8_t pin) { + return (PIN_MAP[pin].gpio_device)->regs->IDR & BIT(pin&0x0F); +} + +/** + * Toggle a pin configured as output push-pull. + * @param dev GPIO device. + * @param pin Pin on dev to toggle. + */ +static inline void gpio_toggle_pin(uint8_t pin) { + (PIN_MAP[pin].gpio_device)->regs->ODR = (PIN_MAP[pin].gpio_device)->regs->ODR ^ BIT(pin&0x0F); +} + +/* + * GPIO Convenience routines + */ + +extern void gpio_init(const gpio_dev *dev); +extern void gpio_init_all(void); +extern void gpio_set_mode(uint8_t pin, gpio_pin_mode mode); +extern void gpio_set_af_mode(uint8_t pin, int mode); + +/* + * AFIO convenience routines + */ + +extern void afio_init(void); +extern void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); +extern void afio_remap(afio_remap_peripheral p); + +/** + * @brief Enable or disable the JTAG and SW debug ports. + * @param config Desired debug port configuration + * @see afio_debug_cfg + */ +static inline void afio_cfg_debug_ports(afio_debug_cfg config) { + //__IO uint32 *mapr = &AFIO_BASE->MAPR; + //*mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; +} + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/STM32F4/cores/maple/libmaple/gpioF1.c b/STM32F4/cores/maple/libmaple/gpioF1.c deleted file mode 100644 index 846b754..0000000 --- a/STM32F4/cores/maple/libmaple/gpioF1.c +++ /dev/null @@ -1,200 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -#ifdef STM32F1 - -/** - * @file gpio.c - * @brief GPIO initialization routine - */ - -#include "gpio.h" -#include "rcc.h" - -/* - * GPIO devices - */ - -gpio_dev gpioa = { - .regs = GPIOA_BASE, - .clk_id = RCC_GPIOA, - .exti_port = AFIO_EXTI_PA, -}; -/** GPIO port A device. */ -gpio_dev* const GPIOA = &gpioa; - -gpio_dev gpiob = { - .regs = GPIOB_BASE, - .clk_id = RCC_GPIOB, - .exti_port = AFIO_EXTI_PB, -}; -/** GPIO port B device. */ -gpio_dev* const GPIOB = &gpiob; - -gpio_dev gpioc = { - .regs = GPIOC_BASE, - .clk_id = RCC_GPIOC, - .exti_port = AFIO_EXTI_PC, -}; -/** GPIO port C device. */ -gpio_dev* const GPIOC = &gpioc; - -gpio_dev gpiod = { - .regs = GPIOD_BASE, - .clk_id = RCC_GPIOD, - .exti_port = AFIO_EXTI_PD, -}; -/** GPIO port D device. */ -gpio_dev* const GPIOD = &gpiod; - -#ifdef STM32_HIGH_DENSITY -gpio_dev gpioe = { - .regs = GPIOE_BASE, - .clk_id = RCC_GPIOE, - .exti_port = AFIO_EXTI_PE, -}; -/** GPIO port E device. */ -gpio_dev* const GPIOE = &gpioe; - -gpio_dev gpiof = { - .regs = GPIOF_BASE, - .clk_id = RCC_GPIOF, - .exti_port = AFIO_EXTI_PF, -}; -/** GPIO port F device. */ -gpio_dev* const GPIOF = &gpiof; - -gpio_dev gpiog = { - .regs = GPIOG_BASE, - .clk_id = RCC_GPIOG, - .exti_port = AFIO_EXTI_PG, -}; -/** GPIO port G device. */ -gpio_dev* const GPIOG = &gpiog; -#endif - -/* - * GPIO convenience routines - */ - -/** - * Initialize a GPIO device. - * - * Enables the clock for and resets the given device. - * - * @param dev GPIO device to initialize. - */ -void gpio_init(gpio_dev *dev) { - rcc_clk_enable(dev->clk_id); - rcc_reset_dev(dev->clk_id); -} - -/** - * Initialize and reset all available GPIO devices. - */ -void gpio_init_all(void) { - gpio_init(GPIOA); - gpio_init(GPIOB); - gpio_init(GPIOC); - gpio_init(GPIOD); -#ifdef STM32_HIGH_DENSITY - gpio_init(GPIOE); - gpio_init(GPIOF); - gpio_init(GPIOG); -#endif -} - -/** - * Set the mode of a GPIO pin. - * - * @param dev GPIO device. - * @param pin Pin on the device whose mode to set, 0--15. - * @param mode General purpose or alternate function mode to set the pin to. - * @see gpio_pin_mode - */ -void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { - gpio_reg_map *regs = dev->regs; - __io uint32 *cr = ®s->CRL + (pin >> 3); - uint32 shift = (pin & 0x7) * 4; - uint32 tmp = *cr; - - tmp &= ~(0xF << shift); - tmp |= (mode == GPIO_INPUT_PU ? GPIO_INPUT_PD : mode) << shift; - *cr = tmp; - - if (mode == GPIO_INPUT_PD) { - regs->ODR &= ~BIT(pin); - } else if (mode == GPIO_INPUT_PU) { - regs->ODR |= BIT(pin); - } -} - -/* - * AFIO - */ - -/** - * @brief Initialize the AFIO clock, and reset the AFIO registers. - */ -void afio_init(void) { - rcc_clk_enable(RCC_AFIO); - rcc_reset_dev(RCC_AFIO); -} - -#define AFIO_EXTI_SEL_MASK 0xF - -/** - * @brief Select a source input for an external interrupt. - * - * @param exti External interrupt. - * @param gpio_port Port which contains pin to use as source input. - * @see afio_exti_num - * @see afio_exti_port - */ -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) { - __io uint32 *exti_cr = &AFIO_BASE->EXTICR1 + exti / 4; - uint32 shift = 4 * (exti % 4); - uint32 cr = *exti_cr; - - cr &= ~(AFIO_EXTI_SEL_MASK << shift); - cr |= gpio_port << shift; - *exti_cr = cr; -} - -/** - * @brief Perform an alternate function remap. - * @param remapping Remapping to perform. - */ -void afio_remap(afio_remap_peripheral remapping) { - if (remapping & AFIO_REMAP_USE_MAPR2) { - remapping &= ~AFIO_REMAP_USE_MAPR2; - AFIO_BASE->MAPR2 |= remapping; - } else { - AFIO_BASE->MAPR |= remapping; - } -} - -#endif diff --git a/STM32F4/cores/maple/libmaple/gpioF1.h b/STM32F4/cores/maple/libmaple/gpioF1.h deleted file mode 100644 index c69efb4..0000000 --- a/STM32F4/cores/maple/libmaple/gpioF1.h +++ /dev/null @@ -1,530 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file gpio.h - * - * @brief General purpose I/O (GPIO) and Alternate Function I/O - * (AFIO) prototypes, defines, and inlined access functions. - */ - -#ifndef _GPIO_H_ -#define _GPIO_H_ - -#include "libmaple.h" -#include "rcc.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - * GPIO register maps and devices - */ - -/** GPIO register map type */ -typedef struct gpio_reg_map { - __io uint32 CRL; /**< Port configuration register low */ - __io uint32 CRH; /**< Port configuration register high */ - __io uint32 IDR; /**< Port input data register */ - __io uint32 ODR; /**< Port output data register */ - __io uint32 BSRR; /**< Port bit set/reset register */ - __io uint32 BRR; /**< Port bit reset register */ - __io uint32 LCKR; /**< Port configuration lock register */ -} gpio_reg_map; - -/** - * @brief External interrupt line port selector. - * - * Used to determine which GPIO port to map an external interrupt line - * onto. */ -/* (See AFIO sections, below) */ -typedef enum afio_exti_port { - AFIO_EXTI_PA, /**< Use port A (PAx) pin. */ - AFIO_EXTI_PB, /**< Use port B (PBx) pin. */ - AFIO_EXTI_PC, /**< Use port C (PCx) pin. */ - AFIO_EXTI_PD, /**< Use port D (PDx) pin. */ -#ifdef STM32_HIGH_DENSITY - AFIO_EXTI_PE, /**< Use port E (PEx) pin. */ - AFIO_EXTI_PF, /**< Use port F (PFx) pin. */ - AFIO_EXTI_PG, /**< Use port G (PGx) pin. */ -#endif -} afio_exti_port; - -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - afio_exti_port exti_port; /**< AFIO external interrupt port value */ -} gpio_dev; - -extern gpio_dev gpioa; -extern gpio_dev* const GPIOA; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOB; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOC; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOD; -#ifdef STM32_HIGH_DENSITY -extern gpio_dev gpioe; -extern gpio_dev* const GPIOE; -extern gpio_dev gpiof; -extern gpio_dev* const GPIOF; -extern gpio_dev gpiog; -extern gpio_dev* const GPIOG; -#endif - -/** GPIO port A register map base pointer */ -#define GPIOA_BASE ((struct gpio_reg_map*)0x40010800) -/** GPIO port B register map base pointer */ -#define GPIOB_BASE ((struct gpio_reg_map*)0x40010C00) -/** GPIO port C register map base pointer */ -#define GPIOC_BASE ((struct gpio_reg_map*)0x40011000) -/** GPIO port D register map base pointer */ -#define GPIOD_BASE ((struct gpio_reg_map*)0x40011400) -#ifdef STM32_HIGH_DENSITY -/** GPIO port E register map base pointer */ -#define GPIOE_BASE ((struct gpio_reg_map*)0x40011800) -/** GPIO port F register map base pointer */ -#define GPIOF_BASE ((struct gpio_reg_map*)0x40011C00) -/** GPIO port G register map base pointer */ -#define GPIOG_BASE ((struct gpio_reg_map*)0x40012000) -#endif - -/* - * GPIO register bit definitions - */ - -/* Control registers, low and high */ - -#define GPIO_CR_CNF (0x3 << 2) -#define GPIO_CR_CNF_INPUT_ANALOG (0x0 << 2) -#define GPIO_CR_CNF_INPUT_FLOATING (0x1 << 2) -#define GPIO_CR_CNF_INPUT_PU_PD (0x2 << 2) -#define GPIO_CR_CNF_OUTPUT_PP (0x0 << 2) -#define GPIO_CR_CNF_OUTPUT_OD (0x1 << 2) -#define GPIO_CR_CNF_AF_OUTPUT_PP (0x2 << 2) -#define GPIO_CR_CNF_AF_OUTPUT_OD (0x3 << 2) -#define GPIO_CR_MODE 0x3 -#define GPIO_CR_MODE_INPUT 0x0 -#define GPIO_CR_MODE_OUTPUT_10MHZ 0x1 -#define GPIO_CR_MODE_OUTPUT_2MHZ 0x2 -#define GPIO_CR_MODE_OUTPUT_50MHZ 0x3 - -/** - * @brief GPIO Pin modes. - * - * These only allow for 50MHZ max output speeds; if you want slower, - * use direct register access. - */ -typedef enum gpio_pin_mode { - GPIO_OUTPUT_PP = (GPIO_CR_CNF_OUTPUT_PP | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output push-pull. */ - GPIO_OUTPUT_OD = (GPIO_CR_CNF_OUTPUT_OD | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output open-drain. */ - GPIO_AF_OUTPUT_PP = (GPIO_CR_CNF_AF_OUTPUT_PP | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function - output push-pull. */ - GPIO_AF_OUTPUT_OD = (GPIO_CR_CNF_AF_OUTPUT_OD | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function - output open drain. */ - GPIO_INPUT_ANALOG = (GPIO_CR_CNF_INPUT_ANALOG | - GPIO_CR_MODE_INPUT), /**< Analog input. */ - GPIO_INPUT_FLOATING = (GPIO_CR_CNF_INPUT_FLOATING | - GPIO_CR_MODE_INPUT), /**< Input floating. */ - GPIO_INPUT_PD = (GPIO_CR_CNF_INPUT_PU_PD | - GPIO_CR_MODE_INPUT), /**< Input pull-down. */ - GPIO_AF_INPUT_PD = (GPIO_INPUT_PD), /**< Input pull-down. */ - GPIO_INPUT_PU /**< Input pull-up. */ - - - /* GPIO_INPUT_PU treated as a special case, for ODR twiddling */ -} gpio_pin_mode; - -/* - * GPIO Convenience routines - */ - -void gpio_init(gpio_dev *dev); -void gpio_init_all(void); -void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); - -/** - * @brief Get a GPIO port's corresponding afio_exti_port. - * @param dev GPIO device whose afio_exti_port to return. - */ -static inline afio_exti_port gpio_exti_port(gpio_dev *dev) { - return dev->exti_port; -} - -/** - * Set or reset a GPIO pin. - * - * Pin must have previously been configured to output mode. - * - * @param dev GPIO device whose pin to set. - * @param pin Pin on to set or reset - * @param val If true, set the pin. If false, reset the pin. - */ -static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { - if (val) { - dev->regs->BSRR = BIT(pin); - } else { - dev->regs->BRR = BIT(pin); - } -} - -/** - * Determine whether or not a GPIO pin is set. - * - * Pin must have previously been configured to input mode. - * - * @param dev GPIO device whose pin to test. - * @param pin Pin on dev to test. - * @return True if the pin is set, false otherwise. - */ -static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { - return dev->regs->IDR & BIT(pin); -} - -/** - * Toggle a pin configured as output push-pull. - * @param dev GPIO device. - * @param pin Pin on dev to toggle. - */ -static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { - dev->regs->ODR = dev->regs->ODR ^ BIT(pin); -} - -/* - * AFIO register map - */ - -/** AFIO register map */ -typedef struct afio_reg_map { - __io uint32 EVCR; /**< Event control register. */ - __io uint32 MAPR; /**< AF remap and debug I/O configuration - register. */ - __io uint32 EXTICR1; /**< External interrupt configuration - register 1. */ - __io uint32 EXTICR2; /**< External interrupt configuration - register 2. */ - __io uint32 EXTICR3; /**< External interrupt configuration - register 3. */ - __io uint32 EXTICR4; /**< External interrupt configuration - register 4. */ - __io uint32 MAPR2; /**< AF remap and debug I/O configuration - register 2. */ -} afio_reg_map; - -/** AFIO register map base pointer. */ -#define AFIO_BASE ((struct afio_reg_map *)0x40010000) - -/* - * AFIO register bit definitions - */ - -/* Event control register */ - -#define AFIO_EVCR_EVOE (0x1 << 7) -#define AFIO_EVCR_PORT_PA (0x0 << 4) -#define AFIO_EVCR_PORT_PB (0x1 << 4) -#define AFIO_EVCR_PORT_PC (0x2 << 4) -#define AFIO_EVCR_PORT_PD (0x3 << 4) -#define AFIO_EVCR_PORT_PE (0x4 << 4) -#define AFIO_EVCR_PIN_0 0x0 -#define AFIO_EVCR_PIN_1 0x1 -#define AFIO_EVCR_PIN_2 0x2 -#define AFIO_EVCR_PIN_3 0x3 -#define AFIO_EVCR_PIN_4 0x4 -#define AFIO_EVCR_PIN_5 0x5 -#define AFIO_EVCR_PIN_6 0x6 -#define AFIO_EVCR_PIN_7 0x7 -#define AFIO_EVCR_PIN_8 0x8 -#define AFIO_EVCR_PIN_9 0x9 -#define AFIO_EVCR_PIN_10 0xA -#define AFIO_EVCR_PIN_11 0xB -#define AFIO_EVCR_PIN_12 0xC -#define AFIO_EVCR_PIN_13 0xD -#define AFIO_EVCR_PIN_14 0xE -#define AFIO_EVCR_PIN_15 0xF - -/* AF remap and debug I/O configuration register */ - -#define AFIO_MAPR_SWJ_CFG (0x7 << 24) -#define AFIO_MAPR_SWJ_CFG_FULL_SWJ (0x0 << 24) -#define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24) -#define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24) -#define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24) -#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20) -#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19) -#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18) -#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17) -#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16) -#define AFIO_MAPR_PD01_REMAP BIT(15) -#define AFIO_MAPR_CAN_REMAP (0x3 << 13) -#define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13) -#define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13) -#define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13) -#define AFIO_MAPR_TIM4_REMAP BIT(12) -#define AFIO_MAPR_TIM3_REMAP (0x3 << 10) -#define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10) -#define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10) -#define AFIO_MAPR_TIM3_REMAP_FULL (0x3 << 10) -#define AFIO_MAPR_TIM2_REMAP (0x3 << 8) -#define AFIO_MAPR_TIM2_REMAP_NONE (0x0 << 8) -#define AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3 (0x1 << 8) -#define AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11 (0x2 << 8) -#define AFIO_MAPR_TIM2_REMAP_FULL (0x3 << 8) -#define AFIO_MAPR_TIM1_REMAP (0x3 << 6) -#define AFIO_MAPR_TIM1_REMAP_NONE (0x0 << 6) -#define AFIO_MAPR_TIM1_REMAP_PARTIAL (0x1 << 6) -#define AFIO_MAPR_TIM1_REMAP_FULL (0x3 << 6) -#define AFIO_MAPR_USART3_REMAP (0x3 << 4) -#define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4) -#define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4) -#define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4) -#define AFIO_MAPR_USART2_REMAP BIT(3) -#define AFIO_MAPR_USART1_REMAP BIT(2) -#define AFIO_MAPR_I2C1_REMAP BIT(1) -#define AFIO_MAPR_SPI1_REMAP BIT(0) - -/* External interrupt configuration register 1 */ - -#define AFIO_EXTICR1_EXTI3 (0xF << 12) -#define AFIO_EXTICR1_EXTI3_PA (0x0 << 12) -#define AFIO_EXTICR1_EXTI3_PB (0x1 << 12) -#define AFIO_EXTICR1_EXTI3_PC (0x2 << 12) -#define AFIO_EXTICR1_EXTI3_PD (0x3 << 12) -#define AFIO_EXTICR1_EXTI3_PE (0x4 << 12) -#define AFIO_EXTICR1_EXTI3_PF (0x5 << 12) -#define AFIO_EXTICR1_EXTI3_PG (0x6 << 12) -#define AFIO_EXTICR1_EXTI2 (0xF << 8) -#define AFIO_EXTICR1_EXTI2_PA (0x0 << 8) -#define AFIO_EXTICR1_EXTI2_PB (0x1 << 8) -#define AFIO_EXTICR1_EXTI2_PC (0x2 << 8) -#define AFIO_EXTICR1_EXTI2_PD (0x3 << 8) -#define AFIO_EXTICR1_EXTI2_PE (0x4 << 8) -#define AFIO_EXTICR1_EXTI2_PF (0x5 << 8) -#define AFIO_EXTICR1_EXTI2_PG (0x6 << 8) -#define AFIO_EXTICR1_EXTI1 (0xF << 4) -#define AFIO_EXTICR1_EXTI1_PA (0x0 << 4) -#define AFIO_EXTICR1_EXTI1_PB (0x1 << 4) -#define AFIO_EXTICR1_EXTI1_PC (0x2 << 4) -#define AFIO_EXTICR1_EXTI1_PD (0x3 << 4) -#define AFIO_EXTICR1_EXTI1_PE (0x4 << 4) -#define AFIO_EXTICR1_EXTI1_PF (0x5 << 4) -#define AFIO_EXTICR1_EXTI1_PG (0x6 << 4) -#define AFIO_EXTICR1_EXTI0 0xF -#define AFIO_EXTICR1_EXTI0_PA 0x0 -#define AFIO_EXTICR1_EXTI0_PB 0x1 -#define AFIO_EXTICR1_EXTI0_PC 0x2 -#define AFIO_EXTICR1_EXTI0_PD 0x3 -#define AFIO_EXTICR1_EXTI0_PE 0x4 -#define AFIO_EXTICR1_EXTI0_PF 0x5 -#define AFIO_EXTICR1_EXTI0_PG 0x6 - -/* External interrupt configuration register 2 */ - -#define AFIO_EXTICR2_EXTI7 (0xF << 12) -#define AFIO_EXTICR2_EXTI7_PA (0x0 << 12) -#define AFIO_EXTICR2_EXTI7_PB (0x1 << 12) -#define AFIO_EXTICR2_EXTI7_PC (0x2 << 12) -#define AFIO_EXTICR2_EXTI7_PD (0x3 << 12) -#define AFIO_EXTICR2_EXTI7_PE (0x4 << 12) -#define AFIO_EXTICR2_EXTI7_PF (0x5 << 12) -#define AFIO_EXTICR2_EXTI7_PG (0x6 << 12) -#define AFIO_EXTICR2_EXTI6 (0xF << 8) -#define AFIO_EXTICR2_EXTI6_PA (0x0 << 8) -#define AFIO_EXTICR2_EXTI6_PB (0x1 << 8) -#define AFIO_EXTICR2_EXTI6_PC (0x2 << 8) -#define AFIO_EXTICR2_EXTI6_PD (0x3 << 8) -#define AFIO_EXTICR2_EXTI6_PE (0x4 << 8) -#define AFIO_EXTICR2_EXTI6_PF (0x5 << 8) -#define AFIO_EXTICR2_EXTI6_PG (0x6 << 8) -#define AFIO_EXTICR2_EXTI5 (0xF << 4) -#define AFIO_EXTICR2_EXTI5_PA (0x0 << 4) -#define AFIO_EXTICR2_EXTI5_PB (0x1 << 4) -#define AFIO_EXTICR2_EXTI5_PC (0x2 << 4) -#define AFIO_EXTICR2_EXTI5_PD (0x3 << 4) -#define AFIO_EXTICR2_EXTI5_PE (0x4 << 4) -#define AFIO_EXTICR2_EXTI5_PF (0x5 << 4) -#define AFIO_EXTICR2_EXTI5_PG (0x6 << 4) -#define AFIO_EXTICR2_EXTI4 0xF -#define AFIO_EXTICR2_EXTI4_PA 0x0 -#define AFIO_EXTICR2_EXTI4_PB 0x1 -#define AFIO_EXTICR2_EXTI4_PC 0x2 -#define AFIO_EXTICR2_EXTI4_PD 0x3 -#define AFIO_EXTICR2_EXTI4_PE 0x4 -#define AFIO_EXTICR2_EXTI4_PF 0x5 -#define AFIO_EXTICR2_EXTI4_PG 0x6 - -/* AF remap and debug I/O configuration register 2 */ - -#define AFIO_MAPR2_FSMC_NADV BIT(10) -#define AFIO_MAPR2_TIM14_REMAP BIT(9) -#define AFIO_MAPR2_TIM13_REMAP BIT(8) -#define AFIO_MAPR2_TIM11_REMAP BIT(7) -#define AFIO_MAPR2_TIM10_REMAP BIT(6) -#define AFIO_MAPR2_TIM9_REMAP BIT(5) - -/* - * AFIO convenience routines - */ - -void afio_init(void); - -/** - * External interrupt line numbers. - */ -typedef enum afio_exti_num { - AFIO_EXTI_0, /**< External interrupt line 0. */ - AFIO_EXTI_1, /**< External interrupt line 1. */ - AFIO_EXTI_2, /**< External interrupt line 2. */ - AFIO_EXTI_3, /**< External interrupt line 3. */ - AFIO_EXTI_4, /**< External interrupt line 4. */ - AFIO_EXTI_5, /**< External interrupt line 5. */ - AFIO_EXTI_6, /**< External interrupt line 6. */ - AFIO_EXTI_7, /**< External interrupt line 7. */ - AFIO_EXTI_8, /**< External interrupt line 8. */ - AFIO_EXTI_9, /**< External interrupt line 9. */ - AFIO_EXTI_10, /**< External interrupt line 10. */ - AFIO_EXTI_11, /**< External interrupt line 11. */ - AFIO_EXTI_12, /**< External interrupt line 12. */ - AFIO_EXTI_13, /**< External interrupt line 13. */ - AFIO_EXTI_14, /**< External interrupt line 14. */ - AFIO_EXTI_15, /**< External interrupt line 15. */ -} afio_exti_num; - -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); - -/* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and - * not used in either MAPR or MAPR2 */ -#define AFIO_REMAP_USE_MAPR2 (1 << 31) - -/** - * @brief Available peripheral remaps. - * @see afio_remap() - */ -typedef enum afio_remap_peripheral { - AFIO_REMAP_ADC2_ETRGREG = AFIO_MAPR_ADC2_ETRGREG_REMAP, /**< - ADC 2 external trigger regular conversion remapping */ - AFIO_REMAP_ADC2_ETRGINJ = AFIO_MAPR_ADC2_ETRGINJ_REMAP, /**< - ADC 2 external trigger injected conversion remapping */ - AFIO_REMAP_ADC1_ETRGREG = AFIO_MAPR_ADC1_ETRGREG_REMAP, /**< - ADC 1 external trigger regular conversion remapping */ - AFIO_REMAP_ADC1_ETRGINJ = AFIO_MAPR_ADC1_ETRGINJ_REMAP, /**< - ADC 1 external trigger injected conversion remapping */ - AFIO_REMAP_TIM5CH4_I = AFIO_MAPR_TIM5CH4_IREMAP, /**< - Timer 5 channel 4 internal remapping */ - AFIO_REMAP_PD01 = AFIO_MAPR_PD01_REMAP, /**< - Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ - AFIO_REMAP_CAN_1 = AFIO_MAPR_CAN_REMAP_PB8_PB9, /**< - CAN alternate function remapping 1 (RX on PB8, TX on PB9) */ - AFIO_REMAP_CAN_2 = AFIO_MAPR_CAN_REMAP_PD0_PD1, /**< - CAN alternate function remapping 2 (RX on PD0, TX on PD1) */ - AFIO_REMAP_TIM4 = AFIO_MAPR_TIM4_REMAP, /**< - Timer 4 remapping */ - AFIO_REMAP_TIM3_PARTIAL = AFIO_MAPR_TIM3_REMAP_PARTIAL, /**< - Timer 3 partial remapping */ - AFIO_REMAP_TIM3_FULL = AFIO_MAPR_TIM3_REMAP_FULL, /**< - Timer 3 full remapping */ - AFIO_REMAP_TIM2_PARTIAL_1 = AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3, /**< - Timer 2 partial remapping 1 (CH1 and ETR on PA15, CH2 on PB3, CH3 - on PA2, CH4 on PA3) */ - AFIO_REMAP_TIM2_PARTIAL_2 = AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11, /**< - Timer 2 partial remapping 2 (CH1 and ETR on PA0, CH2 on PA1, CH3 - on PB10, CH4 on PB11) */ - AFIO_REMAP_TIM2_FULL = AFIO_MAPR_TIM2_REMAP_FULL, /**< - Timer 2 full remapping */ - AFIO_REMAP_USART2 = AFIO_MAPR_USART2_REMAP, /**< - USART 2 remapping */ - AFIO_REMAP_USART1 = AFIO_MAPR_USART1_REMAP, /**< - USART 1 remapping */ - AFIO_REMAP_I2C1 = AFIO_MAPR_I2C1_REMAP, /**< - I2C 1 remapping */ - AFIO_REMAP_SPI1 = AFIO_MAPR_SPI1_REMAP, /**< - SPI 1 remapping */ - AFIO_REMAP_FSMC_NADV = (AFIO_MAPR2_FSMC_NADV | - AFIO_REMAP_USE_MAPR2), /**< - NADV signal not connected */ - AFIO_REMAP_TIM14 = (AFIO_MAPR2_TIM14_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 14 remapping */ - AFIO_REMAP_TIM13 = (AFIO_MAPR2_TIM13_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 13 remapping */ - AFIO_REMAP_TIM11 = (AFIO_MAPR2_TIM11_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 11 remapping */ - AFIO_REMAP_TIM10 = (AFIO_MAPR2_TIM10_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 10 remapping */ - AFIO_REMAP_TIM9 = (AFIO_MAPR2_TIM9_REMAP | - AFIO_REMAP_USE_MAPR2) /**< - Timer 9 */ -} afio_remap_peripheral; - -void afio_remap(afio_remap_peripheral p); - -/** - * @brief Debug port configuration - * - * Used to configure the behavior of JTAG and Serial Wire (SW) debug - * ports and their associated GPIO pins. - * - * @see afio_cfg_debug_ports() - */ -typedef enum afio_debug_cfg { - AFIO_DEBUG_FULL_SWJ = AFIO_MAPR_SWJ_CFG_FULL_SWJ, /**< - Full Serial Wire and JTAG debug */ - AFIO_DEBUG_FULL_SWJ_NO_NJRST = AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST, /**< - Full Serial Wire and JTAG, but no NJTRST. */ - AFIO_DEBUG_SW_ONLY = AFIO_MAPR_SWJ_CFG_NO_JTAG_SW, /**< - Serial Wire debug only (JTAG-DP disabled, - SW-DP enabled) */ - AFIO_DEBUG_NONE = AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW /**< - No debug; all JTAG and SW pins are free - for use as GPIOs. */ -} afio_debug_cfg; - -/** - * @brief Enable or disable the JTAG and SW debug ports. - * @param config Desired debug port configuration - * @see afio_debug_cfg - */ -static inline void afio_cfg_debug_ports(afio_debug_cfg config) { - __io uint32 *mapr = &AFIO_BASE->MAPR; - *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; -} - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/STM32F4/cores/maple/libmaple/gpioF2.c b/STM32F4/cores/maple/libmaple/gpioF4.c similarity index 74% rename from STM32F4/cores/maple/libmaple/gpioF2.c rename to STM32F4/cores/maple/libmaple/gpioF4.c index b04c7e9..0409bcc 100644 --- a/STM32F4/cores/maple/libmaple/gpioF2.c +++ b/STM32F4/cores/maple/libmaple/gpioF4.c @@ -24,8 +24,6 @@ * SOFTWARE. *****************************************************************************/ - #ifdef STM32F2 - /** * @file gpio.c * @brief GPIO initialization routine @@ -38,62 +36,57 @@ * GPIO devices */ -gpio_dev gpioa = { +/** GPIO port A device. */ +const gpio_dev GPIOA = { .regs = GPIOA_BASE, .clk_id = RCC_GPIOA, .exti_port = AFIO_EXTI_PA, }; -/** GPIO port A device. */ -gpio_dev* const GPIOA = &gpioa; -gpio_dev gpiob = { +/** GPIO port B device. */ +const gpio_dev GPIOB = { .regs = GPIOB_BASE, .clk_id = RCC_GPIOB, .exti_port = AFIO_EXTI_PB, }; -/** GPIO port B device. */ -gpio_dev* const GPIOB = &gpiob; -gpio_dev gpioc = { +/** GPIO port C device. */ +const gpio_dev GPIOC = { .regs = GPIOC_BASE, .clk_id = RCC_GPIOC, .exti_port = AFIO_EXTI_PC, }; -/** GPIO port C device. */ -gpio_dev* const GPIOC = &gpioc; -gpio_dev gpiod = { +/** GPIO port D device. */ +const gpio_dev GPIOD = { .regs = GPIOD_BASE, .clk_id = RCC_GPIOD, .exti_port = AFIO_EXTI_PD, }; -/** GPIO port D device. */ -gpio_dev* const GPIOD = &gpiod; #ifdef STM32_HIGH_DENSITY -gpio_dev gpioe = { +/** GPIO port E device. */ +const gpio_dev GPIOE = { .regs = GPIOE_BASE, .clk_id = RCC_GPIOE, .exti_port = AFIO_EXTI_PE, }; -/** GPIO port E device. */ -gpio_dev* const GPIOE = &gpioe; -gpio_dev gpiof = { + #if 0 // not available on LQFP 100 package +/** GPIO port F device. */ +const gpio_dev GPIOF = { .regs = GPIOF_BASE, .clk_id = RCC_GPIOF, .exti_port = AFIO_EXTI_PF, }; -/** GPIO port F device. */ -gpio_dev* const GPIOF = &gpiof; -gpio_dev gpiog = { +/** GPIO port G device. */ +const gpio_dev GPIOG = { .regs = GPIOG_BASE, .clk_id = RCC_GPIOG, .exti_port = AFIO_EXTI_PG, }; -/** GPIO port G device. */ -gpio_dev* const GPIOG = &gpiog; +#endif #endif /* @@ -107,7 +100,7 @@ gpio_dev* const GPIOG = &gpiog; * * @param dev GPIO device to initialize. */ -void gpio_init(gpio_dev *dev) { +void gpio_init(const gpio_dev *dev) { rcc_clk_enable(dev->clk_id); rcc_reset_dev(dev->clk_id); } @@ -116,27 +109,29 @@ void gpio_init(gpio_dev *dev) { * Initialize and reset all available GPIO devices. */ void gpio_init_all(void) { - gpio_init(GPIOA); - gpio_init(GPIOB); - gpio_init(GPIOC); - gpio_init(GPIOD); + gpio_init(&GPIOA); + gpio_init(&GPIOB); + gpio_init(&GPIOC); + gpio_init(&GPIOD); #ifdef STM32_HIGH_DENSITY - gpio_init(GPIOE); - gpio_init(GPIOF); - gpio_init(GPIOG); + gpio_init(&GPIOE); + #if 0 // not available on LQFP 100 package + gpio_init(GPIOF); + gpio_init(GPIOG); + #endif // not available on LQFP 100 package #endif #ifdef ARDUINO_STM32F4_NETDUINO2PLUS // PA8 Output the Master Clock MCO1 - gpio_set_af_mode(GPIOA, 8, 0); - gpio_set_mode(GPIOA, 8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); + gpio_set_af_mode(PA8, 0); + gpio_set_mode(PA8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); // PB4 as alternate MISO Input - gpio_set_af_mode(GPIOB, 4, 5); + gpio_set_af_mode(PB4, 5); // PA5 as alternate SCK Output - gpio_set_af_mode(GPIOA, 5, 5); + gpio_set_af_mode(PA5, 5); // PA7 as alternate MOSI Output - gpio_set_af_mode(GPIOA, 7, 5); + gpio_set_af_mode(PA7, 5); #endif } @@ -148,16 +143,17 @@ void gpio_init_all(void) { * @param mode General purpose or alternate function mode to set the pin to. * @see gpio_pin_mode */ -void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { - gpio_reg_map *regs = dev->regs; +void gpio_set_mode(uint8_t io_pin, gpio_pin_mode mode) { + gpio_reg_map *regs = (PIN_MAP[io_pin].gpio_device)->regs; + uint8_t pin = io_pin&0x0f; //regs->AFR[pin/8] = (regs->AFR[pin/8] & ~(15 << (4*(pin&7)))) | (((mode >> 8) & 15) << (4*(pin&7))); //gpio_set_af_mode(dev, pin, mode>>8); - regs->MODER = (regs->MODER & ~( 3 << (2*pin))) | (((mode >> 0) & 3) << (2*pin)); - regs->PUPDR = (regs->PUPDR & ~( 3 << (2*pin))) | (((mode >> 2) & 3) << (2*pin)); - regs->OSPEEDR = (regs->OSPEEDR & ~( 3 << (2*pin))) | (((mode >> 4) & 3) << (2*pin)); - regs->OTYPER = (regs->OTYPER & ~( 1 << (1*pin))) | (((mode >> 6) & 1) << (1*pin)); + regs->MODER = (regs->MODER & ~( 3 << (pin<<1))) | (((mode >> 0) & 3) << (pin<<1)); + regs->PUPDR = (regs->PUPDR & ~( 3 << (pin<<1))) | (((mode >> 2) & 3) << (pin<<1)); + regs->OSPEEDR = (regs->OSPEEDR & ~( 3 << (pin<<1))) | (((mode >> 4) & 3) << (pin<<1)); + regs->OTYPER = (regs->OTYPER & ~( 1 << (pin<<0))) | (((mode >> 6) & 1) << (pin<<0)); } /** @@ -168,10 +164,11 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { * @param mode alternate function mode to set the pin to. * @see gpio_pin_mode */ -void gpio_set_af_mode(gpio_dev *dev, uint8 pin, int mode) { - gpio_reg_map *regs = dev->regs; +void gpio_set_af_mode(uint8_t io_pin, int mode) { + gpio_reg_map *regs = (PIN_MAP[io_pin].gpio_device)->regs; + uint8_t pin = io_pin&0x0F; - regs->AFR[pin/8] = (regs->AFR[pin/8] & ~(15 << (4*(pin&7)))) | (((mode >> 0) & 15) << (4*(pin&7))); + regs->AFR[pin>>3] = (regs->AFR[pin>>3] & ~(15 << ((pin&7)<<2))) | (((mode >> 0) & 15) << ((pin&7)<<2)); } /* @@ -197,7 +194,7 @@ void afio_init(void) { * @see afio_exti_port */ void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) { - __io uint32 *exti_cr = &SYSCFG_BASE->EXTICR1 + exti / 4; + __IO uint32 *exti_cr = &SYSCFG_BASE->EXTICR1 + exti / 4; uint32 shift = 4 * (exti % 4); uint32 cr = *exti_cr; @@ -220,5 +217,3 @@ void afio_remap(afio_remap_peripheral remapping) { } } #endif - -#endif diff --git a/STM32F4/cores/maple/libmaple/gpioF2.h b/STM32F4/cores/maple/libmaple/gpio_def.h similarity index 83% rename from STM32F4/cores/maple/libmaple/gpioF2.h rename to STM32F4/cores/maple/libmaple/gpio_def.h index 91bd67b..4168969 100644 --- a/STM32F4/cores/maple/libmaple/gpioF2.h +++ b/STM32F4/cores/maple/libmaple/gpio_def.h @@ -31,8 +31,8 @@ * (AFIO) prototypes, defines, and inlined access functions. */ -#ifndef _GPIO_H_ -#define _GPIO_H_ +#ifndef _GPIO_DEF_H_ +#define _GPIO_DEF_H_ #include "libmaple.h" #include "rcc.h" @@ -47,16 +47,16 @@ extern "C"{ /** GPIO register map type */ typedef struct gpio_reg_map { - __io uint32 MODER; /*!< GPIO port mode register, Address offset: 0x00 */ - __io uint32 OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ - __io uint32 OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ - __io uint32 PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ - __io uint32 IDR; /*!< GPIO port input data register, Address offset: 0x10 */ - __io uint32 ODR; /*!< GPIO port output data register, Address offset: 0x14 */ - __io uint16 BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ - __io uint16 BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ - __io uint32 LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ - __io uint32 AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x24-0x28 */ + __IO uint32 MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32 OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32 OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32 PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32 IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32 ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint16 BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ + __IO uint16 BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ + __IO uint32 LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32 AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x24-0x28 */ } gpio_reg_map; @@ -74,11 +74,14 @@ typedef enum afio_exti_port { AFIO_EXTI_PD, /**< Use port D (PDx) pin. */ #ifdef STM32_HIGH_DENSITY AFIO_EXTI_PE, /**< Use port E (PEx) pin. */ + #if 0 // not available on LQFP 100 package AFIO_EXTI_PF, /**< Use port F (PFx) pin. */ AFIO_EXTI_PG, /**< Use port G (PGx) pin. */ + #endif // not available on LQFP 100 package #endif } afio_exti_port; + /** GPIO device type */ typedef struct gpio_dev { gpio_reg_map *regs; /**< Register map */ @@ -86,21 +89,18 @@ typedef struct gpio_dev { afio_exti_port exti_port; /**< AFIO external interrupt port value */ } gpio_dev; -extern gpio_dev gpioa; -extern gpio_dev* const GPIOA; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOB; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOC; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOD; +extern const gpio_dev GPIOA; +extern const gpio_dev GPIOB; +extern const gpio_dev GPIOC; +extern const gpio_dev GPIOD; #ifdef STM32_HIGH_DENSITY -extern gpio_dev gpioe; -extern gpio_dev* const GPIOE; +extern const gpio_dev GPIOE; + #if 0 // not available on LQFP 100 package extern gpio_dev gpiof; extern gpio_dev* const GPIOF; extern gpio_dev gpiog; extern gpio_dev* const GPIOG; + #endif // not available on LQFP 100 package #endif /** GPIO port register map base pointer */ @@ -110,8 +110,10 @@ extern gpio_dev* const GPIOG; #define GPIOD_BASE ((struct gpio_reg_map*)0x40020C00) #ifdef STM32_HIGH_DENSITY #define GPIOE_BASE ((struct gpio_reg_map*)0x40021000) + #if 0 // not available on LQFP 100 package #define GPIOF_BASE ((struct gpio_reg_map*)0x40021400) #define GPIOG_BASE ((struct gpio_reg_map*)0x40021800) + #endif // not available on LQFP 100 package #endif /* @@ -123,9 +125,9 @@ extern gpio_dev* const GPIOG; #define GPIO_MODE_AF 2 #define GPIO_MODE_ANALOG 3 -#define GPIO_PUPD_INPUT_FLOATING (0 << 2) -#define GPIO_PUPD_INPUT_PU (1 << 2) -#define GPIO_PUPD_INPUT_PD (2 << 2) +#define GPIO_PUPD_NONE (0 << 2) +#define GPIO_PUPD_PU (1 << 2) +#define GPIO_PUPD_PD (2 << 2) #define GPIO_OSPEED_2MHZ (0 << 4) #define GPIO_OSPEED_25MHZ (1 << 4) @@ -175,76 +177,22 @@ typedef enum gpio_pin_mode { GPIO_AF_OUTPUT_PP = (GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_50MHZ), /**< Alternate function output push-pull. */ + GPIO_AF_OUTPUT_PP_PU = (GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_PUPD_PU | + GPIO_OSPEED_50MHZ), /**< Alternate function + output push-pull. */ GPIO_AF_OUTPUT_OD = (GPIO_MODE_AF | GPIO_OTYPE_OD | GPIO_OSPEED_50MHZ), /**< Alternate function output open drain. */ GPIO_INPUT_ANALOG = (GPIO_MODE_ANALOG), /**< Analog input. */ GPIO_INPUT_FLOATING = (GPIO_MODE_INPUT | - GPIO_PUPD_INPUT_FLOATING), /**< Input floating. */ - GPIO_INPUT_PD = (GPIO_MODE_INPUT | - GPIO_PUPD_INPUT_PD), /**< Input pull-down. */ - GPIO_INPUT_PU = (GPIO_MODE_INPUT | - GPIO_PUPD_INPUT_PU), /**< Input pull-up. */ - GPIO_AF_INPUT_PD = (GPIO_MODE_AF | - GPIO_PUPD_INPUT_PD), /**< Input pull-down. */ + GPIO_PUPD_NONE), /**< Input floating. */ + GPIO_INPUT_PU = (GPIO_MODE_INPUT | GPIO_PUPD_PU), /**< Input pull-up. */ + GPIO_INPUT_PD = (GPIO_MODE_INPUT | GPIO_PUPD_PD), /**< Input pull-down. */ + GPIO_AF_INPUT_PU = (GPIO_MODE_AF | GPIO_PUPD_PU), /**< Alternate input pull-up. */ + GPIO_AF_INPUT_PD = (GPIO_MODE_AF | GPIO_PUPD_PD), /**< Alternate input pull-down. */ GPIO_BIGNUMBER = 0xfff } gpio_pin_mode; -/* - * GPIO Convenience routines - */ - -void gpio_init(gpio_dev *dev); -void gpio_init_all(void); -void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); -void gpio_set_af_mode(gpio_dev *dev, uint8 pin, int mode); - -/** - * @brief Get a GPIO port's corresponding afio_exti_port. - * @param dev GPIO device whose afio_exti_port to return. - */ -static inline afio_exti_port gpio_exti_port(gpio_dev *dev) { - return dev->exti_port; -} - -/** - * Set or reset a GPIO pin. - * - * Pin must have previously been configured to output mode. - * - * @param dev GPIO device whose pin to set. - * @param pin Pin on to set or reset - * @param val If true, set the pin. If false, reset the pin. - */ -static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { - if (val) { - dev->regs->BSRRL = BIT(pin); - } else { - dev->regs->BSRRH = BIT(pin); - } -} - -/** - * Determine whether or not a GPIO pin is set. - * - * Pin must have previously been configured to input mode. - * - * @param dev GPIO device whose pin to test. - * @param pin Pin on dev to test. - * @return True if the pin is set, false otherwise. - */ -static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { - return dev->regs->IDR & BIT(pin); -} - -/** - * Toggle a pin configured as output push-pull. - * @param dev GPIO device. - * @param pin Pin on dev to toggle. - */ -static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { - dev->regs->ODR = dev->regs->ODR ^ BIT(pin); -} /* * AFIO register map @@ -252,13 +200,13 @@ static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { /** AFIO register map */ typedef struct syscfg_reg_map { - __io uint32 MEMRM; /**< memory remap register */ - __io uint32 PMC; /**< peripheral mode configuration register */ - __io uint32 EXTICR1; /**< External interrupt configuration register 1. */ - __io uint32 EXTICR2; /**< External interrupt configuration register 2. */ - __io uint32 EXTICR3; /**< External interrupt configuration register 3. */ - __io uint32 EXTICR4; /**< External interrupt configuration register 4. */ - __io uint32 CMPCR; /**< Compensation cell control register */ + __IO uint32 MEMRM; /**< memory remap register */ + __IO uint32 PMC; /**< peripheral mode configuration register */ + __IO uint32 EXTICR1; /**< External interrupt configuration register 1. */ + __IO uint32 EXTICR2; /**< External interrupt configuration register 2. */ + __IO uint32 EXTICR3; /**< External interrupt configuration register 3. */ + __IO uint32 EXTICR4; /**< External interrupt configuration register 4. */ + __IO uint32 CMPCR; /**< Compensation cell control register */ } syscfg_reg_map; /** AFIO register map base pointer. */ @@ -532,15 +480,6 @@ typedef enum afio_debug_cfg { for use as GPIOs. */ } afio_debug_cfg; -/** - * @brief Enable or disable the JTAG and SW debug ports. - * @param config Desired debug port configuration - * @see afio_debug_cfg - */ -static inline void afio_cfg_debug_ports(afio_debug_cfg config) { - //__io uint32 *mapr = &AFIO_BASE->MAPR; - //*mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; -} #ifdef __cplusplus } diff --git a/STM32F4/cores/maple/libmaple/i2c.c b/STM32F4/cores/maple/libmaple/i2c.c index e3f3199..a582ed0 100644 --- a/STM32F4/cores/maple/libmaple/i2c.c +++ b/STM32F4/cores/maple/libmaple/i2c.c @@ -41,9 +41,9 @@ static i2c_dev i2c_dev1 = { .regs = I2C1_BASE, - .gpio_port = &gpiob, - .sda_pin = 7, - .scl_pin = 6, + //.gpio_port = &gpiob, + .sda_pin = PB7, + .scl_pin = PB6, .clk_id = RCC_I2C1, .ev_nvic_line = NVIC_I2C1_EV, .er_nvic_line = NVIC_I2C1_ER, @@ -54,9 +54,9 @@ i2c_dev* const I2C1 = &i2c_dev1; static i2c_dev i2c_dev2 = { .regs = I2C2_BASE, - .gpio_port = &gpiob, - .sda_pin = 11, - .scl_pin = 10, + //.gpio_port = &gpiob, + .sda_pin = PB11, + .scl_pin = PB10, .clk_id = RCC_I2C2, .ev_nvic_line = NVIC_I2C2_EV, .er_nvic_line = NVIC_I2C2_ER, @@ -336,38 +336,38 @@ void __irq_i2c2_er(void) { */ void i2c_bus_reset(const i2c_dev *dev) { /* Release both lines */ - gpio_write_bit(dev->gpio_port, dev->scl_pin, 1); - gpio_write_bit(dev->gpio_port, dev->sda_pin, 1); - gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_OUTPUT_OD); - gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_OUTPUT_OD); + gpio_set_pin(dev->scl_pin); + gpio_set_pin(dev->sda_pin); + gpio_set_mode(dev->scl_pin, GPIO_OUTPUT_OD); + gpio_set_mode(dev->sda_pin, GPIO_OUTPUT_OD); /* * Make sure the bus is free by clocking it until any slaves release the * bus. */ - while (!gpio_read_bit(dev->gpio_port, dev->sda_pin)) { + while (!gpio_read_pin(dev->sda_pin)) { /* Wait for any clock stretching to finish */ - while (!gpio_read_bit(dev->gpio_port, dev->scl_pin)) + while (!gpio_read_pin(dev->scl_pin)) ; delay_us(10); /* Pull low */ - gpio_write_bit(dev->gpio_port, dev->scl_pin, 0); + gpio_clear_pin(dev->scl_pin); delay_us(10); /* Release high again */ - gpio_write_bit(dev->gpio_port, dev->scl_pin, 1); + gpio_set_pin(dev->scl_pin); delay_us(10); } /* Generate start then stop condition */ - gpio_write_bit(dev->gpio_port, dev->sda_pin, 0); + gpio_clear_pin(dev->sda_pin); delay_us(10); - gpio_write_bit(dev->gpio_port, dev->scl_pin, 0); + gpio_clear_pin(dev->scl_pin); delay_us(10); - gpio_write_bit(dev->gpio_port, dev->scl_pin, 1); + gpio_set_pin(dev->scl_pin); delay_us(10); - gpio_write_bit(dev->gpio_port, dev->sda_pin, 1); + gpio_set_pin(dev->sda_pin); } /** @@ -413,8 +413,8 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) { /* Turn on clock and set GPIO modes */ i2c_init(dev); - gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_AF_OUTPUT_OD); - gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_AF_OUTPUT_OD); + gpio_set_mode(dev->sda_pin, GPIO_AF_OUTPUT_OD); + gpio_set_mode(dev->scl_pin, GPIO_AF_OUTPUT_OD); /* I2C1 and I2C2 are fed from APB1, clocked at 36MHz */ i2c_set_input_clk(dev, I2C_CLK); diff --git a/STM32F4/cores/maple/libmaple/i2c.h b/STM32F4/cores/maple/libmaple/i2c.h index 4c60ad7..674dd35 100644 --- a/STM32F4/cores/maple/libmaple/i2c.h +++ b/STM32F4/cores/maple/libmaple/i2c.h @@ -39,15 +39,15 @@ /** I2C register map type */ typedef struct i2c_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 OAR1; /**< Own address register 1 */ - __io uint32 OAR2; /**< Own address register 2 */ - __io uint32 DR; /**< Data register */ - __io uint32 SR1; /**< Status register 1 */ - __io uint32 SR2; /**< Status register 2 */ - __io uint32 CCR; /**< Clock control register */ - __io uint32 TRISE; /**< TRISE (rise time) register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 OAR1; /**< Own address register 1 */ + __IO uint32 OAR2; /**< Own address register 2 */ + __IO uint32 DR; /**< Data register */ + __IO uint32 SR1; /**< Status register 1 */ + __IO uint32 SR2; /**< Status register 2 */ + __IO uint32 CCR; /**< Clock control register */ + __IO uint32 TRISE; /**< TRISE (rise time) register */ } i2c_reg_map; /** I2C device states */ @@ -78,7 +78,7 @@ typedef struct i2c_msg { */ typedef struct i2c_dev { i2c_reg_map *regs; /**< Register map */ - gpio_dev *gpio_port; /**< SDA, SCL pins' GPIO port */ + //gpio_dev *gpio_port; /**< SDA, SCL pins' GPIO port */ uint8 sda_pin; /**< SDA bit on gpio_port */ uint8 scl_pin; /**< SCL bit on gpio_port */ rcc_clk_id clk_id; /**< RCC clock information */ diff --git a/STM32F4/cores/maple/libmaple/iwdg.h b/STM32F4/cores/maple/libmaple/iwdg.h index 59e8e18..3673e69 100644 --- a/STM32F4/cores/maple/libmaple/iwdg.h +++ b/STM32F4/cores/maple/libmaple/iwdg.h @@ -54,10 +54,10 @@ extern "C"{ /** Independent watchdog register map type. */ typedef struct iwdg_reg_map { - __io uint32 KR; /**< Key register. */ - __io uint32 PR; /**< Prescaler register. */ - __io uint32 RLR; /**< Reload register. */ - __io uint32 SR; /**< Status register */ + __IO uint32 KR; /**< Key register. */ + __IO uint32 PR; /**< Prescaler register. */ + __IO uint32 RLR; /**< Reload register. */ + __IO uint32 SR; /**< Status register */ } iwdg_reg_map; /** Independent watchdog base pointer */ diff --git a/STM32F4/cores/maple/libmaple/libmaple.h b/STM32F4/cores/maple/libmaple/libmaple.h index 10c6c0c..2ec0b28 100644 --- a/STM32F4/cores/maple/libmaple/libmaple.h +++ b/STM32F4/cores/maple/libmaple/libmaple.h @@ -32,29 +32,33 @@ #ifndef _LIBMAPLE_H_ #define _LIBMAPLE_H_ -#include "libmaple_types.h" -#include "stm32.h" #include "util.h" -#include "delay.h" /* * Where to put usercode, based on space reserved for bootloader. * * FIXME this has no business being here */ +/* #if defined(MCU_STM32F103VE) || defined(MCU_STM32F205VE) || defined(MCU_STM32F406VG) - /* e.g., Aeroquad32 */ - #define USER_ADDR_ROM 0x08010000 /* ala42 */ + // e.g., Aeroquad32 + #define USER_ADDR_ROM 0x08010000 // ala42 #define USER_ADDR_RAM 0x20000C00 #define STACK_TOP 0x20000800 #elif defined(BOARD_freeflight) +*/ +#ifndef USER_ADDR_ROM #define USER_ADDR_ROM 0x08000000 -#define USER_ADDR_RAM 0x20000000 +#endif +#define USER_ADDR_RAM 0x20000C00 #define STACK_TOP 0x20000800 +/* #else #define USER_ADDR_ROM 0x08005000 #define USER_ADDR_RAM 0x20000C00 #define STACK_TOP 0x20000800 #endif +*/ + #endif diff --git a/STM32F4/cores/maple/libmaple/libmaple_types.h b/STM32F4/cores/maple/libmaple/libmaple_types.h index 332ded1..4a6b3ec 100644 --- a/STM32F4/cores/maple/libmaple/libmaple_types.h +++ b/STM32F4/cores/maple/libmaple/libmaple_types.h @@ -33,6 +33,8 @@ #ifndef _LIBMAPLE_TYPES_H_ #define _LIBMAPLE_TYPES_H_ +#include + typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; @@ -45,13 +47,16 @@ typedef long long int64; typedef void (*voidFuncPtr)(void); -#define __io volatile -#define __attr_flash __attribute__((section (".USER_FLASH"))) - -#define __always_inline inline __attribute__((always_inline)) - +#define __IO volatile +#define __IO volatile +#ifndef __attr_flash + #define __attr_flash __attribute__((section (".USER_FLASH"))) +#endif +#ifndef __always_inline + #define __always_inline inline __attribute__((always_inline)) +#endif #ifndef NULL -#define NULL 0 + #define NULL 0 #endif #endif diff --git a/STM32F4/cores/maple/libmaple/nvic.h b/STM32F4/cores/maple/libmaple/nvic.h index e3b052d..ace2701 100644 --- a/STM32F4/cores/maple/libmaple/nvic.h +++ b/STM32F4/cores/maple/libmaple/nvic.h @@ -55,19 +55,19 @@ extern "C"{ /** NVIC register map type. */ typedef struct nvic_reg_map { - __io uint32 ISER[8]; /**< Interrupt Set Enable Registers */ + __IO uint32 ISER[8]; /**< Interrupt Set Enable Registers */ uint32 RESERVED0[24]; /**< Reserved */ - __io uint32 ICER[8]; /**< Interrupt Clear Enable Registers */ + __IO uint32 ICER[8]; /**< Interrupt Clear Enable Registers */ uint32 RSERVED1[24]; /**< Reserved */ - __io uint32 ISPR[8]; /**< Interrupt Set Pending Registers */ + __IO uint32 ISPR[8]; /**< Interrupt Set Pending Registers */ uint32 RESERVED2[24]; /**< Reserved */ - __io uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */ + __IO uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */ uint32 RESERVED3[24]; /**< Reserved */ - __io uint32 IABR[8]; /**< Interrupt Active bit Registers */ + __IO uint32 IABR[8]; /**< Interrupt Active bit Registers */ uint32 RESERVED4[56]; /**< Reserved */ - __io uint8 IP[240]; /**< Interrupt Priority Registers */ + __IO uint8 IP[240]; /**< Interrupt Priority Registers */ uint32 RESERVED5[644]; /**< Reserved */ - __io uint32 STIR; /**< Software Trigger Interrupt Registers */ + __IO uint32 STIR; /**< Software Trigger Interrupt Registers */ } nvic_reg_map; /** NVIC register map base pointer. */ diff --git a/STM32F4/cores/maple/libmaple/pwr.h b/STM32F4/cores/maple/libmaple/pwr.h index 88b49c0..c8c4899 100644 --- a/STM32F4/cores/maple/libmaple/pwr.h +++ b/STM32F4/cores/maple/libmaple/pwr.h @@ -37,8 +37,8 @@ extern "C" { /** Power interface register map. */ typedef struct pwr_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 CSR; /**< Control and status register */ + __IO uint32 CR; /**< Control register */ + __IO uint32 CSR; /**< Control and status register */ } pwr_reg_map; /** Power peripheral register map base pointer. */ diff --git a/STM32F4/cores/maple/libmaple/rcc.c b/STM32F4/cores/maple/libmaple/rcc.c deleted file mode 100644 index b3cb9c5..0000000 --- a/STM32F4/cores/maple/libmaple/rcc.c +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file rcc.c - * @brief Implements pretty much only the basic clock setup on the - * stm32, clock enable/disable and peripheral reset commands. - */ - -// #ifdef STM32F2 -// #include "rccF2.c" -// #else -// #include "rccF1.c" -// #endif diff --git a/STM32F4/cores/maple/libmaple/rcc.h b/STM32F4/cores/maple/libmaple/rcc.h index 6317cbd..75e2d3d 100644 --- a/STM32F4/cores/maple/libmaple/rcc.h +++ b/STM32F4/cores/maple/libmaple/rcc.h @@ -29,8 +29,5 @@ * @brief reset and clock control definitions and prototypes */ -#ifdef STM32F2 -#include "rccF2.h" -#else -#include "rccF1.h" -#endif + +#include "rccF4.h" diff --git a/STM32F4/cores/maple/libmaple/rccF1.c b/STM32F4/cores/maple/libmaple/rccF1.c deleted file mode 100644 index 9eb56b8..0000000 --- a/STM32F4/cores/maple/libmaple/rccF1.c +++ /dev/null @@ -1,233 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - - #ifdef STM32F1 - -/** - * @file rcc.c - * @brief Implements pretty much only the basic clock setup on the - * stm32, clock enable/disable and peripheral reset commands. - */ - -#include "libmaple.h" -#include "flash.h" -#include "rcc.h" -#include "bitband.h" - -#define APB1 RCC_APB1 -#define APB2 RCC_APB2 -#define AHB RCC_AHB - -struct rcc_dev_info { - const rcc_clk_domain clk_domain; - const uint8 line_num; -}; - -/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset - * register bit numbers. */ -static const struct rcc_dev_info rcc_dev_table[] = { - [RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 }, - [RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 }, - [RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 }, - [RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 }, - [RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 }, - [RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 }, - [RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 }, - [RCC_ADC3] = { .clk_domain = APB2, .line_num = 15 }, - [RCC_USART1] = { .clk_domain = APB2, .line_num = 14 }, - [RCC_USART2] = { .clk_domain = APB1, .line_num = 17 }, - [RCC_USART3] = { .clk_domain = APB1, .line_num = 18 }, - [RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 }, - [RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 }, - [RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 }, - [RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 }, - [RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 }, - [RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 }, - [RCC_DMA1] = { .clk_domain = AHB, .line_num = 0 }, - [RCC_PWR] = { .clk_domain = APB1, .line_num = 28}, - [RCC_BKP] = { .clk_domain = APB1, .line_num = 27}, - [RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 }, - [RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 }, - [RCC_CRC] = { .clk_domain = AHB, .line_num = 6}, - [RCC_FLITF] = { .clk_domain = AHB, .line_num = 4}, - [RCC_SRAM] = { .clk_domain = AHB, .line_num = 2}, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - [RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 }, - [RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 }, - [RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 }, - [RCC_UART4] = { .clk_domain = APB1, .line_num = 19 }, - [RCC_UART5] = { .clk_domain = APB1, .line_num = 20 }, - [RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, - [RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 }, - [RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 }, - [RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 }, - [RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 }, - [RCC_DAC] = { .clk_domain = APB1, .line_num = 29 }, - [RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 }, - [RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 }, - [RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 }, -#endif -#ifdef STM32_XL_DENSITY - [RCC_TIMER9] = { .clk_domain = APB2, .line_num = 19 }, - [RCC_TIMER10] = { .clk_domain = APB2, .line_num = 20 }, - [RCC_TIMER11] = { .clk_domain = APB2, .line_num = 21 }, - [RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 }, - [RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 }, - [RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 }, -#endif -}; - -/** - * @brief Initialize the clock control system. Initializes the system - * clock source to use the PLL driven by an external oscillator - * @param sysclk_src system clock source, must be PLL - * @param pll_src pll clock source, must be HSE - * @param pll_mul pll multiplier - */ -void rcc_clk_init(rcc_sysclk_src sysclk_src, - rcc_pllsrc pll_src, - rcc_pll_multiplier pll_mul) { - uint32 cfgr = 0; - uint32 cr; - - /* Assume that we're going to clock the chip off the PLL, fed by - * the HSE */ - ASSERT(sysclk_src == RCC_CLKSRC_PLL && - pll_src == RCC_PLLSRC_HSE); - - RCC_BASE->CFGR = pll_src | pll_mul; - - /* Turn on the HSE */ - cr = RCC_BASE->CR; - cr |= RCC_CR_HSEON; - RCC_BASE->CR = cr; - while (!(RCC_BASE->CR & RCC_CR_HSERDY)) - ; - - /* Now the PLL */ - cr |= RCC_CR_PLLON; - RCC_BASE->CR = cr; - while (!(RCC_BASE->CR & RCC_CR_PLLRDY)) - ; - - /* Finally, let's switch over to the PLL */ - cfgr &= ~RCC_CFGR_SW; - cfgr |= RCC_CFGR_SW_PLL; - RCC_BASE->CFGR = cfgr; - while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) - ; -} - -/** - * @brief Turn on the clock line on a peripheral - * @param id Clock ID of the peripheral to turn on. - */ -void rcc_clk_enable(rcc_clk_id id) { - static const __io uint32* enable_regs[] = { - [APB1] = &RCC_BASE->APB1ENR, - [APB2] = &RCC_BASE->APB2ENR, - [AHB] = &RCC_BASE->AHBENR, - }; - - rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io uint32* enr = (__io uint32*)enable_regs[clk_domain]; - uint8 lnum = rcc_dev_table[id].line_num; - - bb_peri_set_bit(enr, lnum, 1); -} - -/** - * @brief Reset a peripheral. - * @param id Clock ID of the peripheral to reset. - */ -void rcc_reset_dev(rcc_clk_id id) { - static const __io uint32* reset_regs[] = { - [APB1] = &RCC_BASE->APB1RSTR, - [APB2] = &RCC_BASE->APB2RSTR, - }; - - rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io void* addr = (__io void*)reset_regs[clk_domain]; - uint8 lnum = rcc_dev_table[id].line_num; - - bb_peri_set_bit(addr, lnum, 1); - bb_peri_set_bit(addr, lnum, 0); -} - -/** - * @brief Get a peripheral's clock domain - * @param id Clock ID of the peripheral whose clock domain to return - * @return Clock source for the given clock ID - */ -rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { - return rcc_dev_table[id].clk_domain; -} - -/** - * @brief Get a peripheral's clock domain speed - * @param id Clock ID of the peripheral whose clock domain speed to return - * @return Clock speed for the given clock ID - */ -uint32 rcc_dev_clk_speed(rcc_clk_id id) { - static const uint32 rcc_dev_clk_speed_table[] = { - [RCC_AHB] = 72000000, - [RCC_APB1] = 36000000, - [RCC_APB2] = 72000000 - }; - return rcc_dev_clk_speed_table[rcc_dev_clk(id)]; -} - -/** - * @brief Get a peripheral's timer clock domain speed - * @param id Clock ID of the peripheral whose clock domain speed to return - * @return Clock speed for the given clock ID - */ -uint32 rcc_dev_timer_clk_speed(rcc_clk_id id) { - return rcc_dev_clk_speed(RCC_APB2); // 72 MHz for all counter -} - -/** - * @brief Set the divider on a peripheral prescaler - * @param prescaler prescaler to set - * @param divider prescaler divider - */ -void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { - static const uint32 masks[] = { - [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE, - [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1, - [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2, - [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE, - [RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE, - }; - - uint32 cfgr = RCC_BASE->CFGR; - cfgr &= ~masks[prescaler]; - cfgr |= divider; - RCC_BASE->CFGR = cfgr; -} - - -#endif diff --git a/STM32F4/cores/maple/libmaple/rccF1.h b/STM32F4/cores/maple/libmaple/rccF1.h deleted file mode 100644 index dd79704..0000000 --- a/STM32F4/cores/maple/libmaple/rccF1.h +++ /dev/null @@ -1,572 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file rcc.h - * @brief reset and clock control definitions and prototypes - */ - -#include "libmaple_types.h" - -#ifndef _RCC_H_ -#define _RCC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/** RCC register map type */ -typedef struct rcc_reg_map { - __io uint32 CR; /**< Clock control register */ - __io uint32 CFGR; /**< Clock configuration register */ - __io uint32 CIR; /**< Clock interrupt register */ - __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ - __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ - __io uint32 AHBENR; /**< AHB peripheral clock enable register */ - __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ - __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ - __io uint32 BDCR; /**< Backup domain control register */ - __io uint32 CSR; /**< Control/status register */ -} rcc_reg_map; - -/** RCC register map base pointer */ -#define RCC_BASE ((struct rcc_reg_map*)0x40021000) - -/* - * Register bit definitions - */ - -/* Clock control register */ - -#define RCC_CR_PLLRDY_BIT 25 -#define RCC_CR_PLLON_BIT 24 -#define RCC_CR_CSSON_BIT 19 -#define RCC_CR_HSEBYP_BIT 18 -#define RCC_CR_HSERDY_BIT 17 -#define RCC_CR_HSEON_BIT 16 -#define RCC_CR_HSIRDY_BIT 1 -#define RCC_CR_HSION_BIT 0 - -#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT) -#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT) -#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT) -#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT) -#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT) -#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT) -#define RCC_CR_HSICAL (0xFF << 8) -#define RCC_CR_HSITRIM (0x1F << 3) -#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT) -#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT) - -/* Clock configuration register */ - -#define RCC_CFGR_USBPRE_BIT 22 -#define RCC_CFGR_PLLXTPRE_BIT 17 -#define RCC_CFGR_PLLSRC_BIT 16 - -#define RCC_CFGR_MCO (0x3 << 24) -#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT) -#define RCC_CFGR_PLLMUL (0xF << 18) -#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT) -#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT) -#define RCC_CFGR_ADCPRE (0x3 << 14) -#define RCC_CFGR_PPRE2 (0x7 << 11) -#define RCC_CFGR_PPRE1 (0x7 << 8) -#define RCC_CFGR_HPRE (0xF << 4) -#define RCC_CFGR_SWS (0x3 << 2) -#define RCC_CFGR_SWS_PLL (0x2 << 2) -#define RCC_CFGR_SWS_HSE (0x1 << 2) -#define RCC_CFGR_SW 0x3 -#define RCC_CFGR_SW_PLL 0x2 -#define RCC_CFGR_SW_HSE 0x1 - -/* Clock interrupt register */ - -#define RCC_CIR_CSSC_BIT 23 -#define RCC_CIR_PLLRDYC_BIT 20 -#define RCC_CIR_HSERDYC_BIT 19 -#define RCC_CIR_HSIRDYC_BIT 18 -#define RCC_CIR_LSERDYC_BIT 17 -#define RCC_CIR_LSIRDYC_BIT 16 -#define RCC_CIR_PLLRDYIE_BIT 12 -#define RCC_CIR_HSERDYIE_BIT 11 -#define RCC_CIR_HSIRDYIE_BIT 10 -#define RCC_CIR_LSERDYIE_BIT 9 -#define RCC_CIR_LSIRDYIE_BIT 8 -#define RCC_CIR_CSSF_BIT 7 -#define RCC_CIR_PLLRDYF_BIT 4 -#define RCC_CIR_HSERDYF_BIT 3 -#define RCC_CIR_HSIRDYF_BIT 2 -#define RCC_CIR_LSERDYF_BIT 1 -#define RCC_CIR_LSIRDYF_BIT 0 - -#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT) -#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT) -#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT) -#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT) -#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT) -#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT) -#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT) -#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT) -#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT) -#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT) -#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT) -#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT) -#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT) -#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT) -#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT) -#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT) -#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT) - -/* APB2 peripheral reset register */ - -#define RCC_APB2RSTR_TIM11RST_BIT 21 -#define RCC_APB2RSTR_TIM10RST_BIT 20 -#define RCC_APB2RSTR_TIM9RST_BIT 19 -#define RCC_APB2RSTR_ADC3RST_BIT 15 -#define RCC_APB2RSTR_USART1RST_BIT 14 -#define RCC_APB2RSTR_TIM8RST_BIT 13 -#define RCC_APB2RSTR_SPI1RST_BIT 12 -#define RCC_APB2RSTR_TIM1RST_BIT 11 -#define RCC_APB2RSTR_ADC2RST_BIT 10 -#define RCC_APB2RSTR_ADC1RST_BIT 9 -#define RCC_APB2RSTR_IOPGRST_BIT 8 -#define RCC_APB2RSTR_IOPFRST_BIT 7 -#define RCC_APB2RSTR_IOPERST_BIT 6 -#define RCC_APB2RSTR_IOPDRST_BIT 5 -#define RCC_APB2RSTR_IOPCRST_BIT 4 -#define RCC_APB2RSTR_IOPBRST_BIT 3 -#define RCC_APB2RSTR_IOPARST_BIT 2 -#define RCC_APB2RSTR_AFIORST_BIT 0 - -#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT) -#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT) -#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT) -#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT) -#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT) -#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT) -#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT) -#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT) -#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT) -#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT) -#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT) -#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT) -#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT) -#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT) -#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT) -#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT) -#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT) -#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT) - -/* APB1 peripheral reset register */ - -#define RCC_APB1RSTR_DACRST_BIT 29 -#define RCC_APB1RSTR_PWRRST_BIT 28 -#define RCC_APB1RSTR_BKPRST_BIT 27 -#define RCC_APB1RSTR_CANRST_BIT 25 -#define RCC_APB1RSTR_USBRST_BIT 23 -#define RCC_APB1RSTR_I2C2RST_BIT 22 -#define RCC_APB1RSTR_I2C1RST_BIT 21 -#define RCC_APB1RSTR_UART5RST_BIT 20 -#define RCC_APB1RSTR_UART4RST_BIT 19 -#define RCC_APB1RSTR_USART3RST_BIT 18 -#define RCC_APB1RSTR_USART2RST_BIT 17 -#define RCC_APB1RSTR_SPI3RST_BIT 15 -#define RCC_APB1RSTR_SPI2RST_BIT 14 -#define RCC_APB1RSTR_WWDRST_BIT 11 -#define RCC_APB1RSTR_TIM14RST_BIT 8 -#define RCC_APB1RSTR_TIM13RST_BIT 7 -#define RCC_APB1RSTR_TIM12RST_BIT 6 -#define RCC_APB1RSTR_TIM7RST_BIT 5 -#define RCC_APB1RSTR_TIM6RST_BIT 4 -#define RCC_APB1RSTR_TIM5RST_BIT 3 -#define RCC_APB1RSTR_TIM4RST_BIT 2 -#define RCC_APB1RSTR_TIM3RST_BIT 1 -#define RCC_APB1RSTR_TIM2RST_BIT 0 - -#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT) -#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT) -#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT) -#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT) -#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT) -#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT) -#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT) -#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT) -#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT) -#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT) -#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT) -#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT) -#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT) -#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT) -#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT) -#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT) -#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT) -#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT) -#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT) -#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT) -#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT) -#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT) -#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT) - -/* AHB peripheral clock enable register */ - -#define RCC_AHBENR_SDIOEN_BIT 10 -#define RCC_AHBENR_FSMCEN_BIT 8 -#define RCC_AHBENR_CRCEN_BIT 7 -#define RCC_AHBENR_FLITFEN_BIT 4 -#define RCC_AHBENR_SRAMEN_BIT 2 -#define RCC_AHBENR_DMA2EN_BIT 1 -#define RCC_AHBENR_DMA1EN_BIT 0 - -#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT) -#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT) -#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT) -#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT) -#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT) -#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT) -#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT) - -/* APB2 peripheral clock enable register */ - -#define RCC_APB2ENR_TIM11EN_BIT 21 -#define RCC_APB2ENR_TIM10EN_BIT 20 -#define RCC_APB2ENR_TIM9EN_BIT 19 -#define RCC_APB2ENR_ADC3EN_BIT 15 -#define RCC_APB2ENR_USART1EN_BIT 14 -#define RCC_APB2ENR_TIM8EN_BIT 13 -#define RCC_APB2ENR_SPI1EN_BIT 12 -#define RCC_APB2ENR_TIM1EN_BIT 11 -#define RCC_APB2ENR_ADC2EN_BIT 10 -#define RCC_APB2ENR_ADC1EN_BIT 9 -#define RCC_APB2ENR_IOPGEN_BIT 8 -#define RCC_APB2ENR_IOPFEN_BIT 7 -#define RCC_APB2ENR_IOPEEN_BIT 6 -#define RCC_APB2ENR_IOPDEN_BIT 5 -#define RCC_APB2ENR_IOPCEN_BIT 4 -#define RCC_APB2ENR_IOPBEN_BIT 3 -#define RCC_APB2ENR_IOPAEN_BIT 2 -#define RCC_APB2ENR_AFIOEN_BIT 0 - -#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT) -#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT) -#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT) -#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT) -#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT) -#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT) -#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT) -#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT) -#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT) -#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT) -#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT) -#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT) -#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT) -#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT) -#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT) -#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT) -#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT) -#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT) - -/* APB1 peripheral clock enable register */ - -#define RCC_APB1ENR_DACEN_BIT 29 -#define RCC_APB1ENR_PWREN_BIT 28 -#define RCC_APB1ENR_BKPEN_BIT 27 -#define RCC_APB1ENR_CANEN_BIT 25 -#define RCC_APB1ENR_USBEN_BIT 23 -#define RCC_APB1ENR_I2C2EN_BIT 22 -#define RCC_APB1ENR_I2C1EN_BIT 21 -#define RCC_APB1ENR_UART5EN_BIT 20 -#define RCC_APB1ENR_UART4EN_BIT 19 -#define RCC_APB1ENR_USART3EN_BIT 18 -#define RCC_APB1ENR_USART2EN_BIT 17 -#define RCC_APB1ENR_SPI3EN_BIT 15 -#define RCC_APB1ENR_SPI2EN_BIT 14 -#define RCC_APB1ENR_WWDEN_BIT 11 -#define RCC_APB1ENR_TIM14EN_BIT 8 -#define RCC_APB1ENR_TIM13EN_BIT 7 -#define RCC_APB1ENR_TIM12EN_BIT 6 -#define RCC_APB1ENR_TIM7EN_BIT 5 -#define RCC_APB1ENR_TIM6EN_BIT 4 -#define RCC_APB1ENR_TIM5EN_BIT 3 -#define RCC_APB1ENR_TIM4EN_BIT 2 -#define RCC_APB1ENR_TIM3EN_BIT 1 -#define RCC_APB1ENR_TIM2EN_BIT 0 - -#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT) -#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT) -#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT) -#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT) -#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT) -#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT) -#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT) -#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT) -#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT) -#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT) -#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT) -#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT) -#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT) -#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT) -#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT) -#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT) -#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT) -#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT) -#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT) -#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT) -#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT) -#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT) -#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT) - -/* Backup domain control register */ - -#define RCC_BDCR_BDRST_BIT 16 -#define RCC_BDCR_RTCEN_BIT 15 -#define RCC_BDCR_LSEBYP_BIT 2 -#define RCC_BDCR_LSERDY_BIT 1 -#define RCC_BDCR_LSEON_BIT 0 - -#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT) -#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT) -#define RCC_BDCR_RTCSEL (0x3 << 8) -#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) -#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) -#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) -#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT) -#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT) -#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT) - -/* Control/status register */ - -#define RCC_CSR_LPWRRSTF_BIT 31 -#define RCC_CSR_WWDGRSTF_BIT 30 -#define RCC_CSR_IWDGRSTF_BIT 29 -#define RCC_CSR_SFTRSTF_BIT 28 -#define RCC_CSR_PORRSTF_BIT 27 -#define RCC_CSR_PINRSTF_BIT 26 -#define RCC_CSR_RMVF_BIT 24 -#define RCC_CSR_LSIRDY_BIT 1 -#define RCC_CSR_LSION_BIT 0 - -#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT) -#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT) -#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT) -#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT) -#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT) -#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT) -#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT) -#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT) -#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT) - -/* - * Convenience routines - */ - -/** - * SYSCLK sources - * @see rcc_clk_init() - */ -typedef enum rcc_sysclk_src { - RCC_CLKSRC_HSI = 0x0, - RCC_CLKSRC_HSE = 0x1, - RCC_CLKSRC_PLL = 0x2, -} rcc_sysclk_src; - -/** - * PLL entry clock source - * @see rcc_clk_init() - */ -typedef enum rcc_pllsrc { - RCC_PLLSRC_HSE = (0x1 << 16), - RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16) -} rcc_pllsrc; - -/** - * PLL multipliers - * @see rcc_clk_init() - */ -typedef enum rcc_pll_multiplier { - RCC_PLLMUL_2 = (0x0 << 18), - RCC_PLLMUL_3 = (0x1 << 18), - RCC_PLLMUL_4 = (0x2 << 18), - RCC_PLLMUL_5 = (0x3 << 18), - RCC_PLLMUL_6 = (0x4 << 18), - RCC_PLLMUL_7 = (0x5 << 18), - RCC_PLLMUL_8 = (0x6 << 18), - RCC_PLLMUL_9 = (0x7 << 18), - RCC_PLLMUL_10 = (0x8 << 18), - RCC_PLLMUL_11 = (0x9 << 18), - RCC_PLLMUL_12 = (0xA << 18), - RCC_PLLMUL_13 = (0xB << 18), - RCC_PLLMUL_14 = (0xC << 18), - RCC_PLLMUL_15 = (0xD << 18), - RCC_PLLMUL_16 = (0xE << 18), -} rcc_pll_multiplier; - -/** - * @brief Identifies bus and clock line for a peripheral. - * - * Also generally useful as a unique identifier for that peripheral - * (or its corresponding device struct). - */ -typedef enum rcc_clk_id { - RCC_GPIOA, - RCC_GPIOB, - RCC_GPIOC, - RCC_GPIOD, - RCC_AFIO, - RCC_ADC1, - RCC_ADC2, - RCC_ADC3, - RCC_USART1, - RCC_USART2, - RCC_USART3, - RCC_TIMER1, - RCC_TIMER2, - RCC_TIMER3, - RCC_TIMER4, - RCC_SPI1, - RCC_SPI2, - RCC_DMA1, - RCC_PWR, - RCC_BKP, - RCC_I2C1, - RCC_I2C2, - RCC_CRC, - RCC_FLITF, - RCC_SRAM, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - RCC_GPIOE, - RCC_GPIOF, - RCC_GPIOG, - RCC_UART4, - RCC_UART5, - RCC_TIMER5, - RCC_TIMER6, - RCC_TIMER7, - RCC_TIMER8, - RCC_FSMC, - RCC_DAC, - RCC_DMA2, - RCC_SDIO, - RCC_SPI3, -#endif -#ifdef STM32_XL_DENSITY - RCC_TIMER9, - RCC_TIMER10, - RCC_TIMER11, - RCC_TIMER12, - RCC_TIMER13, - RCC_TIMER14, -#endif -} rcc_clk_id; - -void rcc_clk_init(rcc_sysclk_src sysclk_src, - rcc_pllsrc pll_src, - rcc_pll_multiplier pll_mul); -void rcc_clk_enable(rcc_clk_id device); -void rcc_reset_dev(rcc_clk_id device); - -typedef enum rcc_clk_domain { - RCC_APB1, - RCC_APB2, - RCC_AHB -} rcc_clk_domain; - -rcc_clk_domain rcc_dev_clk(rcc_clk_id device); - -uint32 rcc_dev_clk_speed(rcc_clk_id id); -uint32 rcc_dev_timer_clk_speed(rcc_clk_id id); - -/** - * Prescaler identifiers - * @see rcc_set_prescaler() - */ -typedef enum rcc_prescaler { - RCC_PRESCALER_AHB, - RCC_PRESCALER_APB1, - RCC_PRESCALER_APB2, - RCC_PRESCALER_USB, - RCC_PRESCALER_ADC -} rcc_prescaler; - -/** - * ADC prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_adc_divider { - RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14, - RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14, - RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14, - RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14, -} rcc_adc_divider; - -/** - * APB1 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb1_divider { - RCC_APB1_HCLK_DIV_1 = 0x0 << 8, - RCC_APB1_HCLK_DIV_2 = 0x4 << 8, - RCC_APB1_HCLK_DIV_4 = 0x5 << 8, - RCC_APB1_HCLK_DIV_8 = 0x6 << 8, - RCC_APB1_HCLK_DIV_16 = 0x7 << 8, -} rcc_apb1_divider; - -/** - * APB2 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb2_divider { - RCC_APB2_HCLK_DIV_1 = 0x0 << 11, - RCC_APB2_HCLK_DIV_2 = 0x4 << 11, - RCC_APB2_HCLK_DIV_4 = 0x5 << 11, - RCC_APB2_HCLK_DIV_8 = 0x6 << 11, - RCC_APB2_HCLK_DIV_16 = 0x7 << 11, -} rcc_apb2_divider; - -/** - * AHB prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_ahb_divider { - RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4, - RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4, - RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4, - RCC_AHB_SYSCLK_DIV_8 = 0xA << 4, - RCC_AHB_SYSCLK_DIV_16 = 0xB << 4, - RCC_AHB_SYSCLK_DIV_32 = 0xC << 4, - RCC_AHB_SYSCLK_DIV_64 = 0xD << 4, - RCC_AHB_SYSCLK_DIV_128 = 0xD << 4, - RCC_AHB_SYSCLK_DIV_256 = 0xE << 4, - RCC_AHB_SYSCLK_DIV_512 = 0xF << 4, -} rcc_ahb_divider; - -void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/STM32F4/cores/maple/libmaple/rccF2.c b/STM32F4/cores/maple/libmaple/rccF4.c similarity index 95% rename from STM32F4/cores/maple/libmaple/rccF2.c rename to STM32F4/cores/maple/libmaple/rccF4.c index 691393a..54cef70 100644 --- a/STM32F4/cores/maple/libmaple/rccF2.c +++ b/STM32F4/cores/maple/libmaple/rccF4.c @@ -24,7 +24,7 @@ * SOFTWARE. *****************************************************************************/ - #ifdef STM32F2 +#ifdef STM32F4 /** * @file rcc.c @@ -144,8 +144,8 @@ static const struct rcc_dev_info rcc_dev_table[] = { typedef struct { - __io uint32 CR; /*!< PWR power control register, Address offset: 0x00 */ - __io uint32 CSR; /*!< PWR power control/status register, Address offset: 0x04 */ + __IO uint32 CR; /*!< PWR power control register, Address offset: 0x00 */ + __IO uint32 CSR; /*!< PWR power control/status register, Address offset: 0x04 */ } PWR_TypeDef; #define PWR_BASE (0x40007000) @@ -154,19 +154,18 @@ typedef struct typedef struct { - __io uint32 ACR; /*!< FLASH access control register, Address offset: 0x00 */ - __io uint32 KEYR; /*!< FLASH key register, Address offset: 0x04 */ - __io uint32 OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */ - __io uint32 SR; /*!< FLASH status register, Address offset: 0x0C */ - __io uint32 CR; /*!< FLASH control register, Address offset: 0x10 */ - __io uint32 OPTCR; /*!< FLASH option control register, Address offset: 0x14 */ + __IO uint32 ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32 KEYR; /*!< FLASH key register, Address offset: 0x04 */ + __IO uint32 OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */ + __IO uint32 SR; /*!< FLASH status register, Address offset: 0x0C */ + __IO uint32 CR; /*!< FLASH control register, Address offset: 0x10 */ + __IO uint32 OPTCR; /*!< FLASH option control register, Address offset: 0x14 */ } FLASH_TypeDef; #define FLASH_R_BASE (0x40023C00) #define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) #define RESET 0 -typedef uint32 uint32_t; void InitMCO1() { @@ -175,8 +174,8 @@ void InitMCO1() RCC->CFGR &= RCC_CFGR_MCO1_RESET_MASK; RCC->CFGR |= RCC_CFGR_MCO1Source_HSE | RCC_CFGR_MCO1Div_1; // PA8 Output the Master Clock MCO1 - gpio_set_af_mode(GPIOA, 8, 0); - gpio_set_mode(GPIOA, 8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); + gpio_set_af_mode(PA8, 0); + gpio_set_mode(PA8, GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); } @@ -599,7 +598,7 @@ void rcc_clk_init2(rcc_sysclk_src sysclk_src, * @param id Clock ID of the peripheral to turn on. */ void rcc_clk_enable(rcc_clk_id id) { - static const __io uint32* enable_regs[] = { + static const __IO uint32* enable_regs[] = { [APB1] = &RCC_BASE->APB1ENR, [APB2] = &RCC_BASE->APB2ENR, [AHB1] = &RCC_BASE->AHB1ENR, @@ -608,7 +607,7 @@ void rcc_clk_enable(rcc_clk_id id) { }; rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io uint32* enr = (__io uint32*)enable_regs[clk_domain]; + __IO uint32* enr = (__IO uint32*)enable_regs[clk_domain]; uint8 lnum = rcc_dev_table[id].line_num; bb_peri_set_bit(enr, lnum, 1); @@ -619,7 +618,7 @@ void rcc_clk_enable(rcc_clk_id id) { * @param id Clock ID of the peripheral to turn on. */ void rcc_clk_disable(rcc_clk_id id) { - static const __io uint32* enable_regs[] = { + static const __IO uint32* enable_regs[] = { [APB1] = &RCC_BASE->APB1ENR, [APB2] = &RCC_BASE->APB2ENR, [AHB1] = &RCC_BASE->AHB1ENR, @@ -628,7 +627,7 @@ void rcc_clk_disable(rcc_clk_id id) { }; rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io uint32* enr = (__io uint32*)enable_regs[clk_domain]; + __IO uint32* enr = (__IO uint32*)enable_regs[clk_domain]; uint8 lnum = rcc_dev_table[id].line_num; bb_peri_set_bit(enr, lnum, 0); @@ -639,7 +638,7 @@ void rcc_clk_disable(rcc_clk_id id) { * @param id Clock ID of the peripheral to reset. */ void rcc_reset_dev(rcc_clk_id id) { - static const __io uint32* reset_regs[] = { + static const __IO uint32* reset_regs[] = { [APB1] = &RCC_BASE->APB1RSTR, [APB2] = &RCC_BASE->APB2RSTR, [AHB1] = &RCC_BASE->AHB1RSTR, @@ -648,7 +647,7 @@ void rcc_reset_dev(rcc_clk_id id) { }; rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io void* addr = (__io void*)reset_regs[clk_domain]; + __IO void* addr = (__IO void*)reset_regs[clk_domain]; uint8 lnum = rcc_dev_table[id].line_num; bb_peri_set_bit(addr, lnum, 1); diff --git a/STM32F4/cores/maple/libmaple/rccF2.h b/STM32F4/cores/maple/libmaple/rccF4.h similarity index 94% rename from STM32F4/cores/maple/libmaple/rccF2.h rename to STM32F4/cores/maple/libmaple/rccF4.h index 99c5ff2..1558bc8 100644 --- a/STM32F4/cores/maple/libmaple/rccF2.h +++ b/STM32F4/cores/maple/libmaple/rccF4.h @@ -42,36 +42,36 @@ extern "C"{ /** RCC register map type */ typedef struct { - __io uint32 CR; /*!< RCC clock control register, Address offset: 0x00 */ - __io uint32 PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ - __io uint32 CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ - __io uint32 CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ - __io uint32 AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ - __io uint32 AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ - __io uint32 AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ + __IO uint32 CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32 PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ + __IO uint32 CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32 CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ + __IO uint32 AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ + __IO uint32 AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ + __IO uint32 AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ uint32 RESERVED0; /*!< Reserved, 0x1C */ - __io uint32 APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ - __io uint32 APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ + __IO uint32 APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ + __IO uint32 APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ uint32 RESERVED1[2]; /*!< Reserved, 0x28-0x2C */ - __io uint32 AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ - __io uint32 AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ - __io uint32 AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ + __IO uint32 AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ + __IO uint32 AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ + __IO uint32 AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ uint32 RESERVED2; /*!< Reserved, 0x3C */ - __io uint32 APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ - __io uint32 APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ + __IO uint32 APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ + __IO uint32 APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ uint32 RESERVED3[2]; /*!< Reserved, 0x48-0x4C */ - __io uint32 AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ - __io uint32 AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ - __io uint32 AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ + __IO uint32 AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ + __IO uint32 AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ + __IO uint32 AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ uint32 RESERVED4; /*!< Reserved, 0x5C */ - __io uint32 APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ - __io uint32 APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ + __IO uint32 APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ + __IO uint32 APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ uint32 RESERVED5[2]; /*!< Reserved, 0x68-0x6C */ - __io uint32 BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ - __io uint32 CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + __IO uint32 BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ + __IO uint32 CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ uint32 RESERVED6[2]; /*!< Reserved, 0x78-0x7C */ - __io uint32 SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ - __io uint32 PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ + __IO uint32 SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ + __IO uint32 PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ } rcc_reg_map; /** RCC register map base pointer */ diff --git a/STM32F4/cores/maple/libmaple/ring_buffer.h b/STM32F4/cores/maple/libmaple/ring_buffer.h index b018522..fbe9f4a 100644 --- a/STM32F4/cores/maple/libmaple/ring_buffer.h +++ b/STM32F4/cores/maple/libmaple/ring_buffer.h @@ -81,7 +81,7 @@ static inline void rb_init(ring_buffer *rb, uint16 size, uint8 *buf) { * @param rb Buffer whose elements to count. */ static inline uint16 rb_full_count(ring_buffer *rb) { - __io ring_buffer *arb = rb; + __IO ring_buffer *arb = rb; int32 size = arb->tail - arb->head; if (arb->tail < arb->head) { size += arb->size + 1; diff --git a/STM32F4/cores/maple/libmaple/rules.mk b/STM32F4/cores/maple/libmaple/rules.mk index c4924dc..eb8d96d 100644 --- a/STM32F4/cores/maple/libmaple/rules.mk +++ b/STM32F4/cores/maple/libmaple/rules.mk @@ -3,17 +3,11 @@ sp := $(sp).x dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -ifneq ($(MCU_FAMILY), STM32F2) -BUILDDIRS += $(BUILD_PATH)/$(d)/usb -BUILDDIRS += $(BUILD_PATH)/$(d)/usb/usb_lib -LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH) -I$(LIBMAPLE_PATH)/usb -I$(LIBMAPLE_PATH)/usb/usb_lib -else BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/STM32_USB_Device_Library/Core/src BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/STM32_USB_Device_Library/Class/cdc/src BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/STM32_USB_OTG_Driver/src BUILDDIRS += $(BUILD_PATH)/$(d)/usbF4/VCP LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH) -I$(LIBMAPLE_PATH)/usbF4 -endif # Local flags @@ -42,18 +36,6 @@ cSRCS_$(d) := adc.c \ usart.c \ util.c -ifneq ($(MCU_FAMILY), STM32F2) - cSRCS_$(d) += \ - usb/descriptors.c \ - usb/usb.c \ - usb/usb_callbacks.c \ - usb/usb_hardware.c \ - usb/usb_lib/usb_core.c \ - usb/usb_lib/usb_init.c \ - usb/usb_lib/usb_int.c \ - usb/usb_lib/usb_mem.c \ - usb/usb_lib/usb_regs.c -else V=1 cSRCS_$(d) += \ usbF4/STM32_USB_Device_Library/Core/src/usbd_core.c \ @@ -69,11 +51,7 @@ else usbF4/VCP/usbd_usr.c \ usbF4/usb.c \ usbF4/VCP/misc.c -endif -ifneq ($(MCU_FAMILY), STM32F2) - cSRCS_$(d) += bkp.c -endif sSRCS_$(d) := exc.S diff --git a/STM32F4/cores/maple/libmaple/scb.h b/STM32F4/cores/maple/libmaple/scb.h index d9cd8c9..b8c4628 100644 --- a/STM32F4/cores/maple/libmaple/scb.h +++ b/STM32F4/cores/maple/libmaple/scb.h @@ -36,26 +36,26 @@ /** System control block register map type */ typedef struct scb_reg_map { - __io uint32 CPUID; /**< CPU ID Base Register */ - __io uint32 ICSR; /**< Interrupt Control State Register */ - __io uint32 VTOR; /**< Vector Table Offset Register */ - __io uint32 AIRCR; /**< Application Interrupt / Reset Control Register */ - __io uint32 SCR; /**< System Control Register */ - __io uint32 CCR; /**< Configuration Control Register */ - __io uint8 SHP[12]; /**< System Handlers Priority Registers + __IO uint32 CPUID; /**< CPU ID Base Register */ + __IO uint32 ICSR; /**< Interrupt Control State Register */ + __IO uint32 VTOR; /**< Vector Table Offset Register */ + __IO uint32 AIRCR; /**< Application Interrupt / Reset Control Register */ + __IO uint32 SCR; /**< System Control Register */ + __IO uint32 CCR; /**< Configuration Control Register */ + __IO uint8 SHP[12]; /**< System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __io uint32 SHCSR; /**< System Handler Control and State Register */ - __io uint32 CFSR; /**< Configurable Fault Status Register */ - __io uint32 HFSR; /**< Hard Fault Status Register */ - __io uint32 DFSR; /**< Debug Fault Status Register */ - __io uint32 MMFAR; /**< Mem Manage Address Register */ - __io uint32 BFAR; /**< Bus Fault Address Register */ - __io uint32 AFSR; /**< Auxiliary Fault Status Register */ - __io uint32 PFR[2]; /**< Processor Feature Register */ - __io uint32 DFR; /**< Debug Feature Register */ - __io uint32 ADR; /**< Auxiliary Feature Register */ - __io uint32 MMFR[4]; /**< Memory Model Feature Register */ - __io uint32 ISAR[5]; /**< ISA Feature Register */ + __IO uint32 SHCSR; /**< System Handler Control and State Register */ + __IO uint32 CFSR; /**< Configurable Fault Status Register */ + __IO uint32 HFSR; /**< Hard Fault Status Register */ + __IO uint32 DFSR; /**< Debug Fault Status Register */ + __IO uint32 MMFAR; /**< Mem Manage Address Register */ + __IO uint32 BFAR; /**< Bus Fault Address Register */ + __IO uint32 AFSR; /**< Auxiliary Fault Status Register */ + __IO uint32 PFR[2]; /**< Processor Feature Register */ + __IO uint32 DFR; /**< Debug Feature Register */ + __IO uint32 ADR; /**< Auxiliary Feature Register */ + __IO uint32 MMFR[4]; /**< Memory Model Feature Register */ + __IO uint32 ISAR[5]; /**< ISA Feature Register */ } scb_reg_map; /** System control block register map base pointer */ diff --git a/STM32F4/cores/maple/libmaple/sdio.c b/STM32F4/cores/maple/libmaple/sdio.c new file mode 100644 index 0000000..1a9113a --- /dev/null +++ b/STM32F4/cores/maple/libmaple/sdio.c @@ -0,0 +1,194 @@ +/****************************************************************************** + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/sdio.c + * @author stevstrong + * @brief Secure digital input/output interface. + */ + +#include "sdio.h" +#include "gpio.h" +#include "wirish_time.h" + +#if defined(BOARD_generic_f407v) + +sdio_dev * SDIO = SDIO_BASE; + +#define DELAY_LONG 10 +#define DELAY_SHORT 1 + +uint8_t dly = DELAY_LONG; // microseconds delay after accessing registers + +/* + * SDIO convenience routines + */ +static void sdio_gpios_init(void) +{ + gpio_set_mode(BOARD_SDIO_D0, GPIO_AF_OUTPUT_PP_PU); + gpio_set_mode(BOARD_SDIO_D1, GPIO_AF_OUTPUT_PP_PU); + gpio_set_mode(BOARD_SDIO_D2, GPIO_AF_OUTPUT_PP_PU); + gpio_set_mode(BOARD_SDIO_D3, GPIO_AF_OUTPUT_PP_PU); + gpio_set_mode(BOARD_SDIO_CLK, GPIO_AF_OUTPUT_PP); + gpio_set_mode(BOARD_SDIO_CMD, GPIO_AF_OUTPUT_PP_PU); + // + gpio_set_af_mode(BOARD_SDIO_D0, 12); + gpio_set_af_mode(BOARD_SDIO_D1, 12); + gpio_set_af_mode(BOARD_SDIO_D2, 12); + gpio_set_af_mode(BOARD_SDIO_D3, 12); + gpio_set_af_mode(BOARD_SDIO_CLK, 12); + gpio_set_af_mode(BOARD_SDIO_CMD, 12); +} + +static void sdio_gpios_deinit(void) +{ + gpio_set_mode(BOARD_SDIO_D0, GPIO_INPUT_FLOATING); + gpio_set_mode(BOARD_SDIO_D1, GPIO_INPUT_FLOATING); + gpio_set_mode(BOARD_SDIO_D2, GPIO_INPUT_FLOATING); + gpio_set_mode(BOARD_SDIO_D3, GPIO_INPUT_FLOATING); + gpio_set_mode(BOARD_SDIO_CLK, GPIO_INPUT_FLOATING); + gpio_set_mode(BOARD_SDIO_CMD, GPIO_INPUT_FLOATING); + // + gpio_set_af_mode(BOARD_SDIO_D0, 0); + gpio_set_af_mode(BOARD_SDIO_D1, 0); + gpio_set_af_mode(BOARD_SDIO_D2, 0); + gpio_set_af_mode(BOARD_SDIO_D3, 0); + gpio_set_af_mode(BOARD_SDIO_CLK, 0); + gpio_set_af_mode(BOARD_SDIO_CMD, 0); +} + +/** + * @brief Initialize and reset the SDIO device. + */ +void sdio_init(void) +{ + rcc_clk_enable(RCC_SDIO); + rcc_reset_dev(RCC_SDIO); +} + +void sdio_power_on(void) +{ + SDIO->POWER = SDIO_POWER_PWRCTRL_ON; +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. + delayMicroseconds(DELAY_LONG); +} + +void sdio_power_off(void) +{ + SDIO->POWER = SDIO_POWER_PWRCTRL_OFF; +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. + delayMicroseconds(DELAY_LONG); +} + +/** + * @brief Enable the SDIO peripheral + +void sdio_peripheral_enable(void) { + bb_peri_set_bit(SDIO->CR1, SPI_CR1_SPE_BIT, 1); +} + */ +/** + * @brief Disable a SPI peripheral + +void sdio_peripheral_disable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 0); +} + */ +void sdio_set_clock(uint32_t clk) +{ + if (clk>24000000UL) clk = 24000000UL; // limit the SDIO master clock to 24MHz + + if (clk<1000000) dly = DELAY_LONG; + else dly = DELAY_SHORT; + + sdio_disable(); + SDIO->CLKCR = (SDIO->CLKCR & (~(SDIO_CLKCR_CLKDIV|SDIO_CLKCR_BYPASS))) | SDIO_CLKCR_CLKEN | (((SDIOCLK/clk)-2)&SDIO_CLKCR_CLKDIV); + delayMicroseconds(dly); +} + +void sdio_set_dbus_width(uint16_t bus_w) +{ + SDIO->CLKCR = (SDIO->CLKCR & (~SDIO_CLKCR_WIDBUS)) | bus_w; + delayMicroseconds(dly); +} + +void sdio_set_dblock_size(uint8_t dbsize) +{ + SDIO->DCTRL = (SDIO->DCTRL&(~SDIO_DCTRL_DBLOCKSIZE)) | ((dbsize&0xF)<<4); + delayMicroseconds(dly); +} + +void sdio_enable(void) +{ + SDIO->CLKCR |= SDIO_CLKCR_CLKEN; + delayMicroseconds(dly); +} + +void sdio_disable(void) +{ + SDIO->CLKCR ^= SDIO_CLKCR_CLKEN; + delayMicroseconds(dly); +} + +/** + * @brief Configure and enable the SDIO device. + */ +void sdio_begin(void) +{ + sdio_gpios_init(); + sdio_init(); + sdio_power_on(); + // Set initial SCK rate. + sdio_set_clock(400000); + delayMicroseconds(200); // generate 80 pulses at 400kHz +} + +/** + * @brief Disables the SDIO device. + */ +void sdio_end(void) +{ + sdio_disable(); + while ( sdio_cmd_xfer_ongoing() ); + sdio_power_off(); + rcc_clk_disable(RCC_SDIO); + sdio_gpios_deinit(); +} + +/** + * @brief Send command by the SDIO device. + */ +uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg) +{ + uint8_t retries = 10; // in case of errors + do { // retry command if errors detected + // clear interrupt flags - IMPORTANT!!! + SDIO->ICR = SDIO_ICR_CMD_FLAGS; + // write command + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)(SDIO_CMD_CPSMEN | cmd_index_resp_type ); + while ( (SDIO->STA&SDIO_STA_CMDACT) ) ; // wait for actual command transfer to finish + // wait for response, if the case + if ( cmd_index_resp_type&(SDIO_CMD_WAIT_SHORT_RESP|SDIO_CMD_WAIT_LONG_RESP) ) { + while ( !(SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CMD_ERROR_FLAGS)) ) ; + } else break; // no response required + if ( SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CTIMEOUT) ) + break; // response received or timeout + // ignore CRC error for CMD5 and ACMD41 + if ( ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==5) || ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==41) ) + break; + } while ( (--retries) ); + return (uint8_t)retries; +} + +#endif // BOARD_generic_f407v diff --git a/STM32F4/cores/maple/libmaple/sdio.h b/STM32F4/cores/maple/libmaple/sdio.h new file mode 100644 index 0000000..4096224 --- /dev/null +++ b/STM32F4/cores/maple/libmaple/sdio.h @@ -0,0 +1,250 @@ +/****************************************************************************** + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file sdio.h + * @brief Secure digital input/output interface. + */ + +#ifndef _SDIO_H_ +#define _SDIO_H_ + + +#include "libmaple_types.h" + + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifdef STM32_HIGH_DENSITY + +/* + * Register maps and devices + */ + +// SDIO register map type +typedef struct sdio_reg_map { + __IO uint32 POWER; // 0x00 + __IO uint32 CLKCR; // 0x04 + __IO uint32 ARG; // 0x08 + __IO uint32 CMD; // 0x0C + __IO uint32 RESPCMD; // 0x10 (0x3F) + const uint32 RESP[4]; // 0x14 - contain the card status, which is part of the received response. + __IO uint32 DTIMER; // 0x24 - contains the data timeout period, in card bus clock periods. + __IO uint32 DLEN; // 0x28 (0x01FF FFFF) - contains the number of data bytes to be transferred + __IO uint32 DCTRL; // 0x2C + __IO uint32 DCOUNT; // 0x30 (0x01FF FFFF) + __IO uint32 STA; // 0x34 + __IO uint32 ICR; // 0x38 + __IO uint32 MASK; // 0x3C + const uint32 RESERVED1[2]; + __IO uint32 FIFOCNT; // 0x48 (0x01FF FFFF) + const uint32 RESERVED2[13]; + __IO uint32 FIFO; // 0x80 +} sdio_reg_map; +#define sdio_dev sdio_reg_map + +/** SDIO register map base pointer */ +#define SDIO_BASE ((struct sdio_reg_map*)0x40012C00) + +extern sdio_dev * SDIO; + +/* + * Register bit definitions + */ + +/* NOR/PSRAM chip-select control registers */ + +// SDIO_POWER register bits +// At least seven HCLK clock periods are needed between two write accesses to this register. +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +#define SDIO_POWER_PWRCTRL_OFF 0x00 +#define SDIO_POWER_PWRCTRL_ON 0x03 + +// SDIO_CLKCR register bits +// Controls the SDIO_CK output clock. +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. SDIO_CK can also be stopped during the read wait interval +// for SD I/O cards: in this case the SDIO_CLKCR register does not control SDIO_CK. +#define SDIO_CLKCR_HWFC_EN (1<<14) // HW Flow Control enable - DON'T USE!!! (see errata sheet 2.12.1) + // Overrun errors (Rx mode) and FIFO underrun (Tx mode) + // should be managed by the application software. +#define SDIO_CLKCR_NEGEDGE (1<<13) // SDIO_CK de-phasing selection bit - DON'T USE!!! (see errata sheet 2.12.4) +#define SDIO_CLKCR_WIDBUS (3<<11) // Data bus width +#define SDIO_CLKCR_WIDBUS_1BIT (0<<11) // 1 bit (SDIO_D0 used) +#define SDIO_CLKCR_WIDBUS_4BIT (1<<11) // 4-bit (SDIO_D[3:0] used) +#define SDIO_CLKCR_BYPASS (1<<10) // Clock divider bypass enable bit - SDIO_CK = SDIOCLK, CLKDIV not relevant. +#define SDIO_CLKCR_PWRSAV (1<<9) // 0: SDIO_CK clock is always enabled, 1: SDIO_CK is only enabled when the bus is active +#define SDIO_CLKCR_CLKEN (1<<8) // Clock enable +#define SDIO_CLKCR_CLKDIV (0xFF) // SDIO_CK = SDIOCLK / [CLKDIV + 2] +#define SDIOCLK 48000000UL // SDIO master clock frequency + +// SDIO_CMD register bits +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +// MultiMediaCards can send two kinds of response: short responses, 48 bits long, or long +// responses,136 bits long. SD card and SD I/O card can send only short responses, the +// argument can vary according to the type of response: the software will distinguish the type +// of response according to the sent command. CE-ATA devices send only short responses. +#define SDIO_CMD_ATACMD (1<<14) +#define SDIO_CMD_NIEN (1<<13) +#define SDIO_CMD_ENCMDCOMPL (1<<12) +#define SDIO_CMD_SDIOSUSPEND (1<<11) +#define SDIO_CMD_CPSMEN (1<<10) +#define SDIO_CMD_WAITPEND (1<<9) +#define SDIO_CMD_WAITINT (1<<8) +#define SDIO_CMD_WAITRESP (3<<6) +#define SDIO_CMD_WAIT_NO_RESP (0<<6) +#define SDIO_CMD_WAIT_SHORT_RESP (1<<6) +#define SDIO_CMD_WAIT_LONG_RESP (3<<6) +#define SDIO_CMD_CMDINDEX (0x3F) + +// SDIO_DLEN register bits +// For a block data transfer, the value in the data length register must be a multiple of the block +// size (see SDIO_DCTRL). A data transfer must be written to the data timer register and the +// data length register before being written to the data control register. +// For an SDIO multibyte transfer the value in the data length register must be between 1 and 512. +#define SDIO_DLEN_DATALENGTH (0x01FFFFFF) + +// SDIO_DCTRL register bits +// Controls the data path state machine (DPSM). +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +#define SDIO_DCTRL_SDIOEN (1<<11) // the DPSM performs an SD I/O-card-specific operation. +#define SDIO_DCTRL_RWMODE (1<<10) // 0: Read Wait control stopping SDIO_D2, 1:Read Wait control using SDIO_CK +#define SDIO_DCTRL_RWSTOP (1<<9) // 0: Read wait in progress if RWSTART bit is set, 1: Enable for read wait stop if RWSTART bit is set +#define SDIO_DCTRL_RWSTART (1<<8) // read wait operation starts +#define SDIO_DCTRL_DBLOCKSIZE (0xF<<4) // Define the data block length when the block data transfer mode is selected: 2^N bytes +#define SDIO_BLOCKSIZE_64 (6<<4) +#define SDIO_BLOCKSIZE_512 (9<<4) +#define SDIO_DCTRL_DMAEN (1<<3) // DMA enable +#define SDIO_DCTRL_DTMODE (1<<2) // Data transfer mode selection: 0: Block data transfer, 1: Stream or SDIO multi-byte data transfer +#define SDIO_DCTRL_DTDIR (1<<1) // Data transfer direction selection: 0: From controller to card, 1: From card to controller. +#define SDIO_DIR_TX (0<<1) +#define SDIO_DIR_RX (1<<1) +#define SDIO_DCTRL_DTEN (1<<0) // Start data transfer. Depending on the direction bit, DTDIR, + // the DPSM moves to the Wait_S, Wait_R state or Readwait if RW Start is set immediately at + // the beginning of the transfer. It is not necessary to clear the enable bit after the end of a data + // transfer but the SDIO_DCTRL must be updated to enable a new data transfer +// The meaning of the DTMODE bit changes according to the value of the SDIOEN bit: +// When DTEN=0 and DTMODE=1, the MultiMediaCard stream mode is enabled. +// When DTEN=1 and DTMODE=1, the peripheral enables an SDIO multi-byte transfer. + +// SDIO_STA register bits +#define SDIO_STA_CEATAEND (1<<23) // CE-ATA command completion signal received for CMD61 +#define SDIO_STA_SDIOIT (1<<22) // SDIO interrupt received +#define SDIO_STA_RXDAVL (1<<21) // Data available in receive FIFO +#define SDIO_STA_TXDAVL (1<<20) // Data available in transmit FIFO +#define SDIO_STA_RXFIFOE (1<<19) // Receive FIFO empty +#define SDIO_STA_TXFIFOE (1<<18) // Transmit FIFO empty (2 words) +#define SDIO_STA_RXFIFOF (1<<17) // Receive FIFO full (2 words before the FIFO is full.) +#define SDIO_STA_TXFIFOF (1<<16) // Transmit FIFO full +#define SDIO_STA_RXFIFOHF (1<<15) // Receive FIFO half full: there are at least 8 words in the FIFO +#define SDIO_STA_TXFIFOHE (1<<14) // Transmit FIFO half empty: at least 8 words can be written into the FIFO +#define SDIO_STA_RXACT (1<<13) // Data receive in progress +#define SDIO_STA_TXACT (1<<12) // Data transmit in progress +#define SDIO_STA_CMDACT (1<<11) // Command transfer in progress +#define SDIO_STA_DBCKEND (1<<10) // Data block sent/received (CRC check passed) +#define SDIO_STA_STBITERR (1<<9) // Start bit not detected on all data signals in wide bus mode +#define SDIO_STA_DATAEND (1<<8) // Data end (data counter SDIOCOUNT is zero) +#define SDIO_STA_CMDSENT (1<<7) // Command sent (no response required) +#define SDIO_STA_CMDREND (1<<6) // Command response received (CRC check passed) +#define SDIO_STA_RXOVERR (1<<5) // Received FIFO overrun error +#define SDIO_STA_TXUNDERR (1<<4) // Transmit FIFO underrun error +#define SDIO_STA_DTIMEOUT (1<<3) // Data timeout +#define SDIO_STA_CTIMEOUT (1<<2) // Command response timeout. The Command TimeOut period has a fixed value of 64 SDIO_CK clock periods. +#define SDIO_STA_DCRCFAIL (1<<1) // Data block sent/received (CRC check failed) +#define SDIO_STA_CCRCFAIL (1<<0) // Command response received (CRC check failed) + +#define SDIO_STA_CMD_ERROR_FLAGS (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL) +#define SDIO_STA_TRX_ERROR_FLAGS (SDIO_STA_STBITERR | SDIO_STA_RXOVERR | SDIO_STA_TXUNDERR | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL) +#define SDIO_STA_TRX_ACT_FLAGS (SDIO_STA_RXACT|SDIO_STA_TXACT) + +// SDIO_ICR register bits (WO - write only) +#define SDIO_ICR_CEATAENDC (1<<23) // clear CEATAEND flag +#define SDIO_ICR_SDIOITC (1<<22) // clear SDIOIT flag +#define SDIO_ICR_DBCKENDC (1<<10) // clear DBCKENDC flag +#define SDIO_ICR_STBITERRC (1<<9) // clear STBITERRC flag +#define SDIO_ICR_DATAENDC (1<<8) // clear DATAENDC flag +#define SDIO_ICR_CMDSENTC (1<<7) // clear CMDSENTC flag +#define SDIO_ICR_CMDRENDC (1<<6) // clear CMDREND flag +#define SDIO_ICR_RXOVERRC (1<<5) // clear RXOVERR flag +#define SDIO_ICR_TXUNDERRC (1<<4) // clear TXUNDERR flag +#define SDIO_ICR_DTIMEOUTC (1<<3) // clear DTIMEOUT flag +#define SDIO_ICR_CTIMEOUTC (1<<2) // clear CTIMEOUT flag +#define SDIO_ICR_DCRCFAILC (1<<1) // clear DCRCFAIL flag +#define SDIO_ICR_CCRCFAILC (1<<0) // clear CCRCFAIL flag + +#define SDIO_ICR_CMD_FLAGS (SDIO_ICR_CEATAENDC | SDIO_ICR_SDIOITC | SDIO_ICR_CMDSENTC | SDIO_ICR_CMDRENDC | SDIO_ICR_CTIMEOUTC | SDIO_ICR_CCRCFAILC) +#define SDIO_ICR_DATA_FLAGS (SDIO_ICR_DBCKENDC | SDIO_ICR_STBITERRC | SDIO_ICR_DATAENDC | SDIO_ICR_RXOVERRC | SDIO_ICR_TXUNDERRC | SDIO_ICR_DTIMEOUTC | SDIO_ICR_DCRCFAILC) + +// SDIO_MASK register bits +// Determines which status flags generate an interrupt request by setting the corresponding bit to 1b. +#define SDIO_MASK_CEATAENDIE (1<<23) // enable CEATAEND interrupt +#define SDIO_MASK_SDIOITIE (1<<22) // enable SDIOIT interrupt +#define SDIO_MASK_RXDAVLIE (1<<21) // enable RXDAVL interrupt +#define SDIO_MASK_TXDAVLIE (1<<20) // enable TXDAVL interrupt +#define SDIO_MASK_RXFIFOEIE (1<<19) // enable RXFIFOE interrupt +#define SDIO_MASK_TXFIFOEIE (1<<18) // enable TXFIFOE interrupt +#define SDIO_MASK_RXFIFOFIE (1<<17) // enable RXFIFOF interrupt +#define SDIO_MASK_TXFIFOFIE (1<<16) // enable TXFIFOF interrupt +#define SDIO_MASK_RXFIFOHFIE (1<<15) // enable RXFIFOHF interrupt +#define SDIO_MASK_TXFIFOHEIE (1<<14) // enable TXFIFOHE interrupt +#define SDIO_MASK_RXACTIE (1<<13) // enable RXACT interrupt +#define SDIO_MASK_TXACTIE (1<<12) // enable TXACT interrupt +#define SDIO_MASK_CMDACTIE (1<<11) // enable CMDACT interrupt +#define SDIO_MASK_DBCKENDIE (1<<10) // enable DBCKENDC interrupt +#define SDIO_MASK_STBITERRIE (1<<9) // enable STBITERR interrupt +#define SDIO_MASK_DATAENDIE (1<<8) // enable DATAENDC interrupt +#define SDIO_MASK_CMDSENTIE (1<<7) // enable CMDSENTC interrupt +#define SDIO_MASK_CMDRENDIE (1<<6) // enable CMDREND interrupt +#define SDIO_MASK_RXOVERRIE (1<<5) // enable RXOVERR interrupt +#define SDIO_MASK_TXUNDERRIE (1<<4) // enable TXUNDERR interrupt +#define SDIO_MASK_DTIMEOUTIE (1<<3) // enable DTIMEOUT interrupt +#define SDIO_MASK_CTIMEOUTIE (1<<2) // enable CTIMEOUT interrupt +#define SDIO_MASK_DCRCFAILIE (1<<1) // enable DCRCFAIL interrupt +#define SDIO_MASK_CCRCFAILIE (1<<0) // enable CCRCFAIL interrupt + + +void sdio_enable(void); +void sdio_disable(void); +void sdio_begin(void); +uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg); +void sdio_set_clock(uint32_t clk); +void sdio_set_dbus_width(uint16_t bus_w); +void sdio_set_dblock_size(uint8_t dbsize); +//void sdio_trx_enable(uint8_t dir); +inline void sdio_trx_enable(void) +{ + SDIO->DCTRL |= SDIO_DCTRL_DTEN; // enable data transfer +} + +inline uint32_t sdio_cmd_xfer_ongoing(void) { return (SDIO->STA&SDIO_STA_CMDACT); } +inline uint32_t sdio_cmd_complete(void) { return (SDIO->STA&SDIO_STA_CMDSENT); } + +inline void sdio_setup_transfer(uint32_t dtimer, uint32_t dlen, uint16_t flags) +{ + SDIO->ICR = SDIO_ICR_DATA_FLAGS; // clear data access relevant flags + SDIO->DTIMER = dtimer; + SDIO->DLEN = dlen; + SDIO->DCTRL = flags;// | SDIO_DCTRL_DTEN; // enable data transfer +} + +#endif /* STM32_HIGH_DENSITY */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/STM32F4/cores/maple/libmaple/spi.c b/STM32F4/cores/maple/libmaple/spi.c index 194a82e..4b274cb 100644 --- a/STM32F4/cores/maple/libmaple/spi.c +++ b/STM32F4/cores/maple/libmaple/spi.c @@ -83,25 +83,29 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) { } /** - * @brief Nonblocking SPI transmit. + * @brief Blocking SPI transmit. * @param dev SPI port to use for transmission * @param buf Buffer to transmit. The sizeof buf's elements are * inferred from dev's data frame format (i.e., are * correctly treated as 8-bit or 16-bit quantities). * @param len Maximum number of elements to transmit. - * @return Number of elements transmitted. */ -uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) { - uint32 txed = 0; - uint8 byte_frame = spi_dff(dev) == SPI_DFF_8_BIT; - while (spi_is_tx_empty(dev) && (txed < len)) { - if (byte_frame) { - dev->regs->DR = ((const uint8*)buf)[txed++]; - } else { - dev->regs->DR = ((const uint16*)buf)[txed++]; - } - } - return txed; +void spi_tx(spi_dev *dev, void *buf, uint32 len) +{ + spi_reg_map *regs = dev->regs; + if ( spi_dff(dev) == SPI_DFF_8_BIT ) { + uint8 * dp8 = (uint8*)buf; + while ( len-- ) { + while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty + regs->DR = *dp8++; + } + } else { + uint16 * dp16 = (uint16*)buf; + while ( len-- ) { + while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty + regs->DR = *dp16++; + } + } } /** @@ -157,8 +161,9 @@ void spi_rx_dma_disable(spi_dev *dev) { */ static void spi_reconfigure(spi_dev *dev, uint32 cr1_config) { - spi_irq_disable(dev, SPI_INTERRUPTS_ALL); - spi_peripheral_disable(dev); - dev->regs->CR1 = cr1_config; - spi_peripheral_enable(dev); +#define MASK (SPI_CR1_CRCEN|SPI_CR1_DFF) + spi_irq_disable(dev, SPI_INTERRUPTS_ALL); + if ( (dev->regs->CR1&MASK)!=(cr1_config&MASK) ) spi_peripheral_disable(dev); + dev->regs->CR1 = cr1_config; + spi_peripheral_enable(dev); } diff --git a/STM32F4/cores/maple/libmaple/spi.h b/STM32F4/cores/maple/libmaple/spi.h index 88739c5..3a18a2e 100644 --- a/STM32F4/cores/maple/libmaple/spi.h +++ b/STM32F4/cores/maple/libmaple/spi.h @@ -53,15 +53,15 @@ extern "C" { /** SPI register map type. */ typedef struct spi_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SR; /**< Status register */ - __io uint32 DR; /**< Data register */ - __io uint32 CRCPR; /**< CRC polynomial register */ - __io uint32 RXCRCR; /**< RX CRC register */ - __io uint32 TXCRCR; /**< TX CRC register */ - __io uint32 I2SCFGR; /**< I2S configuration register */ - __io uint32 I2SPR; /**< I2S prescaler register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SR; /**< Status register */ + __IO uint32 DR; /**< Data register */ + __IO uint32 CRCPR; /**< CRC polynomial register */ + __IO uint32 RXCRCR; /**< RX CRC register */ + __IO uint32 TXCRCR; /**< TX CRC register */ + __IO uint32 I2SCFGR; /**< I2S configuration register */ + __IO uint32 I2SPR; /**< I2S prescaler register */ } spi_reg_map; /* @@ -213,31 +213,22 @@ typedef struct spi_dev { void spi_init(spi_dev *dev); -struct gpio_dev; /** * @brief Configure GPIO bit modes for use as a SPI port's pins. * * @param dev SPI device * @param as_master If true, configure as bus master; otherwise, as slave. - * @param nss_dev NSS pin's GPIO device * @param nss_bit NSS pin's GPIO bit on nss_dev - * @param sck_dev SCK pin's GPIO device * @param sck_bit SCK pin's GPIO bit on comm_dev - * @param miso_dev MISO pin's GPIO device * @param miso_bit MISO pin's GPIO bit on comm_dev - * @param mosi_dev MOSI pin's GPIO device * @param mosi_bit MOSI pin's GPIO bit on comm_dev */ extern void spi_config_gpios(spi_dev *dev, uint8 as_master, - struct gpio_dev *nss_dev, - uint8 nss_bit, - struct gpio_dev *sck_dev, - uint8 sck_bit, - struct gpio_dev *miso_dev, - uint8 miso_bit, - struct gpio_dev *mosi_dev, - uint8 mosi_bit); + uint8 nss_pin, + uint8 sck_pin, + uint8 miso_pin, + uint8 mosi_pin); /** * @brief SPI mode configuration. @@ -312,7 +303,7 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags); -uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len); +void spi_tx(spi_dev *dev, void *buf, uint32 len); /** * @brief Call a function on each SPI port diff --git a/STM32F4/cores/maple/libmaple/spiF4.h b/STM32F4/cores/maple/libmaple/spiF4.h index 3f51164..cbdc91a 100644 --- a/STM32F4/cores/maple/libmaple/spiF4.h +++ b/STM32F4/cores/maple/libmaple/spiF4.h @@ -31,8 +31,8 @@ * @brief STM32F1 SPI/I2S series header. */ -#ifndef _LIBMAPLE_STM32F1_SPI_H_ -#define _LIBMAPLE_STM32F1_SPI_H_ +#ifndef _LIBMAPLE_SPI_F4_H_ +#define _LIBMAPLE_SPI_F4_H_ #include @@ -62,17 +62,6 @@ extern struct spi_dev *SPI2; extern struct spi_dev *SPI3; #endif -/* - * Routines - */ - -/* spi_gpio_cfg(): Backwards compatibility shim to spi_config_gpios() */ -struct gpio_dev; -extern void spi_config_gpios(struct spi_dev*, uint8, - struct gpio_dev*, uint8, - struct gpio_dev*, uint8, - struct gpio_dev*, uint8, - struct gpio_dev*, uint8); #ifdef __cplusplus } diff --git a/STM32F4/cores/maple/libmaple/spi_f4.c b/STM32F4/cores/maple/libmaple/spi_f4.c index b9beb68..f52853e 100644 --- a/STM32F4/cores/maple/libmaple/spi_f4.c +++ b/STM32F4/cores/maple/libmaple/spi_f4.c @@ -54,28 +54,31 @@ spi_dev *SPI3 = &spi3; * Routines */ -void spi_config_gpios(spi_dev *ignored, +void spi_config_gpios(spi_dev *dev, uint8 as_master, - gpio_dev *nss_dev, - uint8 nss_bit, - gpio_dev *sck_dev, - uint8 sck_bit, - gpio_dev *miso_dev, - uint8 miso_bit, - gpio_dev *mosi_dev, - uint8 mosi_bit) { + uint8 nss_pin, + uint8 sck_pin, + uint8 miso_pin, + uint8 mosi_pin) { if (as_master) { -// gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(sck_dev, sck_bit, GPIO_AF_OUTPUT_PP); -// gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING); - gpio_set_mode(miso_dev, miso_bit, GPIO_AF_INPUT_PD); - gpio_set_mode(mosi_dev, mosi_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(sck_pin, GPIO_AF_OUTPUT_PP); + gpio_set_mode(miso_pin, GPIO_AF_INPUT_PD); + gpio_set_mode(mosi_pin, GPIO_AF_OUTPUT_PP); } else { - gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING); - gpio_set_mode(sck_dev, sck_bit, GPIO_INPUT_FLOATING); - gpio_set_mode(miso_dev, miso_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(mosi_dev, mosi_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(nss_pin, GPIO_INPUT_FLOATING); + gpio_set_mode(sck_pin, GPIO_INPUT_FLOATING); + gpio_set_mode(miso_pin, GPIO_AF_OUTPUT_PP); + gpio_set_mode(mosi_pin, GPIO_INPUT_FLOATING); } + + uint8_t af_mode = 6; + if(dev->clk_id <= RCC_SPI2) { af_mode = 5; } + if(!as_master) { + gpio_set_af_mode(nss_pin, af_mode); + } + gpio_set_af_mode(sck_pin, af_mode); + gpio_set_af_mode(miso_pin, af_mode); + gpio_set_af_mode(mosi_pin, af_mode); } void spi_foreach(void (*fn)(spi_dev*)) { diff --git a/STM32F4/cores/maple/libmaple/stm32.h b/STM32F4/cores/maple/libmaple/stm32.h index 0d4deaa..3921788 100644 --- a/STM32F4/cores/maple/libmaple/stm32.h +++ b/STM32F4/cores/maple/libmaple/stm32.h @@ -138,69 +138,8 @@ #endif -#if defined(MCU_STM32F103RB) - /* e.g., LeafLabs Maple */ - #define STM32_NR_GPIO_PORTS 4 - #define STM32_DELAY_US_MULT 12 - #define STM32_SRAM_END ((void*)0x20005000) - - #define NR_GPIO_PORTS STM32_NR_GPIO_PORTS - #define DELAY_US_MULT STM32_DELAY_US_MULT - -#elif defined(MCU_STM32F103ZE) - /* e.g., LeafLabs Maple Native */ - - #define STM32_NR_GPIO_PORTS 7 - #define STM32_DELAY_US_MULT 12 - #define STM32_SRAM_END ((void*)0x20010000) - - #define NR_GPIO_PORTS STM32_NR_GPIO_PORTS - #define DELAY_US_MULT STM32_DELAY_US_MULT - -#elif defined(MCU_STM32F103CB) - /* e.g., LeafLabs Maple Mini */ - - /* This STM32_NR_GPIO_PORTS value is not, strictly speaking, true. - * But only pins 0 and 1 exist, and they're used for OSC on the - * Mini, so we'll live with this for now. */ - #define STM32_NR_GPIO_PORTS 3 - #define STM32_DELAY_US_MULT 12 - #define STM32_SRAM_END ((void*)0x20005000) - - #define NR_GPIO_PORTS STM32_NR_GPIO_PORTS - #define DELAY_US_MULT STM32_DELAY_US_MULT - -#elif defined(MCU_STM32F103RE) - /* e.g., LeafLabs Maple RET6 edition */ - - #define STM32_NR_GPIO_PORTS 4 - #define STM32_DELAY_US_MULT 12 - #define STM32_SRAM_END ((void*)0x20010000) - - #define NR_GPIO_PORTS STM32_NR_GPIO_PORTS - #define DELAY_US_MULT STM32_DELAY_US_MULT - -#elif defined(MCU_STM32F103VE) - /* e.g., LeafLabs Maple Native */ - - #define STM32_NR_GPIO_PORTS 5 - #define STM32_DELAY_US_MULT 12 - #define STM32_SRAM_END ((void*)0x20010000) - - #define NR_GPIO_PORTS STM32_NR_GPIO_PORTS - #define DELAY_US_MULT STM32_DELAY_US_MULT - -#elif defined(MCU_STM32F205VE) - #define STM32_TICKS_PER_US 120 - #define STM32_NR_GPIO_PORTS 5 - #define STM32_DELAY_US_MULT (STM32_TICKS_PER_US/3) - #define STM32_SRAM_END ((void*)0x20010000) - - #define NR_GPIO_PORTS STM32_NR_GPIO_PORTS - #define DELAY_US_MULT STM32_DELAY_US_MULT - -#elif defined(MCU_STM32F406VG) +#if defined( STM32F4 ) #define STM32_TICKS_PER_US 168 #define STM32_NR_GPIO_PORTS 5 #define STM32_DELAY_US_MULT (STM32_TICKS_PER_US/3) diff --git a/STM32F4/cores/maple/libmaple/systick.h b/STM32F4/cores/maple/libmaple/systick.h index 6ec3364..8db8ec0 100644 --- a/STM32F4/cores/maple/libmaple/systick.h +++ b/STM32F4/cores/maple/libmaple/systick.h @@ -42,10 +42,10 @@ extern "C"{ /** SysTick register map type */ typedef struct systick_reg_map { - __io uint32 CSR; /**< Control and status register */ - __io uint32 RVR; /**< Reload value register */ - __io uint32 CNT; /**< Current value register ("count") */ - __io uint32 CVR; /**< Calibration value register */ + __IO uint32 CSR; /**< Control and status register */ + __IO uint32 RVR; /**< Reload value register */ + __IO uint32 CNT; /**< Current value register ("count") */ + __IO uint32 CVR; /**< Calibration value register */ } systick_reg_map; /** SysTick register map base pointer */ diff --git a/STM32F4/cores/maple/libmaple/timer.c b/STM32F4/cores/maple/libmaple/timer.c index 83e9ace..f8e55a1 100644 --- a/STM32F4/cores/maple/libmaple/timer.c +++ b/STM32F4/cores/maple/libmaple/timer.c @@ -44,7 +44,7 @@ /* Update only. */ #define NR_BAS_HANDLERS 1 -static timer_dev timer1 = { +timer_dev timer1 = { .regs = { .adv = TIMER1_BASE }, .clk_id = RCC_TIMER1, .type = TIMER_ADVANCED, @@ -53,7 +53,7 @@ static timer_dev timer1 = { /** Timer 1 device (advanced) */ timer_dev *TIMER1 = &timer1; -static timer_dev timer2 = { +timer_dev timer2 = { .regs = { .gen = TIMER2_BASE }, .clk_id = RCC_TIMER2, .type = TIMER_GENERAL, @@ -62,7 +62,7 @@ static timer_dev timer2 = { /** Timer 2 device (general-purpose) */ timer_dev *TIMER2 = &timer2; -static timer_dev timer3 = { +timer_dev timer3 = { .regs = { .gen = TIMER3_BASE }, .clk_id = RCC_TIMER3, .type = TIMER_GENERAL, @@ -71,7 +71,7 @@ static timer_dev timer3 = { /** Timer 3 device (general-purpose) */ timer_dev *TIMER3 = &timer3; -static timer_dev timer4 = { +timer_dev timer4 = { .regs = { .gen = TIMER4_BASE }, .clk_id = RCC_TIMER4, .type = TIMER_GENERAL, @@ -81,7 +81,7 @@ static timer_dev timer4 = { timer_dev *TIMER4 = &timer4; #ifdef STM32_HIGH_DENSITY -static timer_dev timer5 = { +timer_dev timer5 = { .regs = { .gen = TIMER5_BASE }, .clk_id = RCC_TIMER5, .type = TIMER_GENERAL, @@ -90,7 +90,7 @@ static timer_dev timer5 = { /** Timer 5 device (general-purpose) */ timer_dev *TIMER5 = &timer5; -static timer_dev timer6 = { +timer_dev timer6 = { .regs = { .bas = TIMER6_BASE }, .clk_id = RCC_TIMER6, .type = TIMER_BASIC, @@ -99,7 +99,7 @@ static timer_dev timer6 = { /** Timer 6 device (basic) */ timer_dev *TIMER6 = &timer6; -static timer_dev timer7 = { +timer_dev timer7 = { .regs = { .bas = TIMER7_BASE }, .clk_id = RCC_TIMER7, .type = TIMER_BASIC, @@ -108,7 +108,7 @@ static timer_dev timer7 = { /** Timer 7 device (basic) */ timer_dev *TIMER7 = &timer7; -static timer_dev timer8 = { +timer_dev timer8 = { .regs = { .adv = TIMER8_BASE }, .clk_id = RCC_TIMER8, .type = TIMER_ADVANCED, diff --git a/STM32F4/cores/maple/libmaple/timer.h b/STM32F4/cores/maple/libmaple/timer.h index fce6345..4336397 100644 --- a/STM32F4/cores/maple/libmaple/timer.h +++ b/STM32F4/cores/maple/libmaple/timer.h @@ -50,76 +50,71 @@ extern "C"{ /** Advanced control timer register map type */ typedef struct timer_adv_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ - __io uint32 RCR; /**< Repetition counter register */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ - __io uint32 BDTR; /**< Break and dead-time register */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SMCR; /**< Slave mode control register */ + __IO uint32 DIER; /**< DMA/Interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ + __IO uint32 CCMR1; /**< Capture/compare mode register 1 */ + __IO uint32 CCMR2; /**< Capture/compare mode register 2 */ + __IO uint32 CCER; /**< Capture/compare enable register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ + __IO uint32 RCR; /**< Repetition counter register */ + __IO uint32 CCR1; /**< Capture/compare register 1 */ + __IO uint32 CCR2; /**< Capture/compare register 2 */ + __IO uint32 CCR3; /**< Capture/compare register 3 */ + __IO uint32 CCR4; /**< Capture/compare register 4 */ + __IO uint32 BDTR; /**< Break and dead-time register */ + __IO uint32 DCR; /**< DMA control register */ + __IO uint32 DMAR; /**< DMA address for full transfer */ } timer_adv_reg_map; /** General purpose timer register map type */ typedef struct timer_gen_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 SMCR; /**< Slave mode control register */ + __IO uint32 DIER; /**< DMA/Interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ + __IO uint32 CCMR1; /**< Capture/compare mode register 1 */ + __IO uint32 CCMR2; /**< Capture/compare mode register 2 */ + __IO uint32 CCER; /**< Capture/compare enable register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ const uint32 RESERVED1; /**< Reserved */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ + __IO uint32 CCR1; /**< Capture/compare register 1 */ + __IO uint32 CCR2; /**< Capture/compare register 2 */ + __IO uint32 CCR3; /**< Capture/compare register 3 */ + __IO uint32 CCR4; /**< Capture/compare register 4 */ const uint32 RESERVED2; /**< Reserved */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ + __IO uint32 DCR; /**< DMA control register */ + __IO uint32 DMAR; /**< DMA address for full transfer */ } timer_gen_reg_map; /** Basic timer register map type */ typedef struct timer_bas_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ const uint32 RESERVED1; /**< Reserved */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ + __IO uint32 DIER; /**< DMA/Interrupt enable register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 EGR; /**< Event generation register */ const uint32 RESERVED2; /**< Reserved */ const uint32 RESERVED3; /**< Reserved */ const uint32 RESERVED4; /**< Reserved */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ + __IO uint32 CNT; /**< Counter */ + __IO uint32 PSC; /**< Prescaler */ + __IO uint32 ARR; /**< Auto-reload register */ } timer_bas_reg_map; -#ifdef STM32F2 - /** Timer 1 register map base pointer */ - #define TIMER1_BASE ((struct timer_adv_reg_map*)0x40010000) -#else - /** Timer 1 register map base pointer */ - #define TIMER1_BASE ((struct timer_adv_reg_map*)0x40012C00) -#endif +/** Timer 1 register map base pointer */ +#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40010000) /** Timer 2 register map base pointer */ #define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000) /** Timer 3 register map base pointer */ @@ -133,14 +128,8 @@ typedef struct timer_bas_reg_map { #define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000) /** Timer 7 register map base pointer */ #define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400) - -#ifdef STM32F2 - /** Timer 8 register map base pointer */ - #define TIMER8_BASE ((struct timer_adv_reg_map*)0x40010400) -#else - /** Timer 8 register map base pointer */ - #define TIMER8_BASE ((struct timer_adv_reg_map*)0x40013400) -#endif +/** Timer 8 register map base pointer */ +#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40010400) #endif /* @@ -706,7 +695,7 @@ static inline void timer_set_reload(timer_dev *dev, uint16 arr) { * @param channel Channel whose compare value to get. */ static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) { - __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); + __IO uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); return *ccr; } @@ -719,7 +708,7 @@ static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) { static inline void timer_set_compare(timer_dev *dev, uint8 channel, uint16 value) { - __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); + __IO uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); *ccr = value; } @@ -1010,7 +999,7 @@ static inline void timer_oc_set_mode(timer_dev *dev, //uint8 bit1 = (channel >> 1) & 1; // original uint8 bit1 = ((channel-1) >> 1) & 1; // fixed /* channel == 1,2 -> CCMR1; channel == 3,4 -> CCMR2 */ - __io uint32 *ccmr = &(dev->regs).gen->CCMR1 + bit1; + __IO uint32 *ccmr = &(dev->regs).gen->CCMR1 + bit1; /* channel == 1,3 -> shift = 0, channel == 2,4 -> shift = 8 */ uint8 shift = 8 * (1 - bit0); diff --git a/STM32F4/cores/maple/libmaple/usart.h b/STM32F4/cores/maple/libmaple/usart.h index 3f7c885..fddb5f2 100644 --- a/STM32F4/cores/maple/libmaple/usart.h +++ b/STM32F4/cores/maple/libmaple/usart.h @@ -52,21 +52,17 @@ extern "C"{ /** USART register map type */ typedef struct usart_reg_map { - __io uint32 SR; /**< Status register */ - __io uint32 DR; /**< Data register */ - __io uint32 BRR; /**< Baud rate register */ - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 CR3; /**< Control register 3 */ - __io uint32 GTPR; /**< Guard time and prescaler register */ + __IO uint32 SR; /**< Status register */ + __IO uint32 DR; /**< Data register */ + __IO uint32 BRR; /**< Baud rate register */ + __IO uint32 CR1; /**< Control register 1 */ + __IO uint32 CR2; /**< Control register 2 */ + __IO uint32 CR3; /**< Control register 3 */ + __IO uint32 GTPR; /**< Guard time and prescaler register */ } usart_reg_map; /** USART1 register map base pointer */ -#ifdef STM32F2 - #define USART1_BASE ((struct usart_reg_map*)0x40011000) -#else - #define USART1_BASE ((struct usart_reg_map*)0x40013800) -#endif +#define USART1_BASE ((struct usart_reg_map*)0x40011000) /** USART2 register map base pointer */ #define USART2_BASE ((struct usart_reg_map*)0x40004400) /** USART3 register map base pointer */ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/audio/inc/usbd_audio_core.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/audio/inc/usbd_audio_core.h index f58ff06..69f7ffa 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/audio/inc/usbd_audio_core.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/audio/inc/usbd_audio_core.h @@ -26,7 +26,7 @@ #include "usbd_ioreq.h" #include "usbd_req.h" -#include "usbd_desc.h" +#include diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h index 926f42e..29a38e9 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc/usbd_cdc_core.h @@ -24,7 +24,8 @@ #ifndef __USB_CDC_CORE_H_ #define __USB_CDC_CORE_H_ -#include "usbd_ioreq.h" +#include +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c index aac6776..8963a8a 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c @@ -58,9 +58,10 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usbd_cdc_core.h" -#include "usbd_desc.h" -#include "usbd_req.h" +#include +#include +#include +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_core.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_core.h index b876856..3e4db9b 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_core.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_core.h @@ -24,9 +24,9 @@ #define __USBD_CORE_H /* Includes ------------------------------------------------------------------*/ -#include "usb_dcd.h" +#include #include "usbd_def.h" -#include "usbd_conf.h" +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_def.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_def.h index a8c8671..03a8afc 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_def.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_def.h @@ -24,7 +24,7 @@ #ifndef __USBD_DEF_H #define __USBD_DEF_H /* Includes ------------------------------------------------------------------*/ -#include "usbd_conf.h" +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_req.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_req.h index 9aa9e44..fd3c055 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_req.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/inc/usbd_req.h @@ -27,7 +27,7 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_def.h" #include "usbd_core.h" -#include "usbd_conf.h" +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_core.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_core.c index af75842..2c5e822 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_core.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_core.c @@ -20,11 +20,11 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usbd_core.h" -#include "usbd_req.h" -#include "usbd_ioreq.h" -#include "usb_dcd_int.h" -#include "usb_bsp.h" +#include +#include +#include +#include +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_ioreq.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_ioreq.c index 6964766..620b9e5 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_ioreq.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_ioreq.c @@ -20,7 +20,7 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usbd_ioreq.h" +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_req.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_req.c index f08d26c..2233d15 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_req.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_Device_Library/Core/src/usbd_req.c @@ -20,9 +20,9 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usbd_req.h" -#include "usbd_ioreq.h" -#include "usbd_desc.h" +#include +#include +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_core.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_core.h index 82a09e1..dd6a86a 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_core.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_core.h @@ -24,7 +24,7 @@ #define __USB_CORE_H__ /* Includes ------------------------------------------------------------------*/ -#include "usb_conf.h" +#include #include "usb_regs.h" #include "usb_defines.h" diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_defines.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_defines.h index 8c23d72..546f5ab 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_defines.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_defines.h @@ -24,7 +24,7 @@ #define __USB_DEF_H__ /* Includes ------------------------------------------------------------------*/ -#include "usb_conf.h" +#include /** @addtogroup USB_OTG_DRIVER * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_otg.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_otg.h index 54d61b8..1347f31 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_otg.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_otg.h @@ -23,6 +23,7 @@ #ifndef __USB_OTG__ #define __USB_OTG__ +#include "usb_core.h" /** @addtogroup USB_OTG_DRIVER * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_regs.h b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_regs.h index cd71ddf..3038f0d 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_regs.h +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/inc/usb_regs.h @@ -24,8 +24,8 @@ #define __USB_OTG_REGS_H__ /* Includes ------------------------------------------------------------------*/ -#include "usb_conf.h" - +#include +#include /** @addtogroup USB_OTG_DRIVER * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_core.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_core.c index cb9eabc..dd3856f 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_core.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_core.c @@ -20,8 +20,8 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usb_bsp.h" -#include "usb_core.h" +#include +#include /** @addtogroup USB_OTG_DRIVER diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd.c index c3336cb..0d23a97 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd.c @@ -20,8 +20,8 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usb_dcd.h" -#include "usb_bsp.h" +#include +#include /** @addtogroup USB_OTG_DRIVER diff --git a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd_int.c b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd_int.c index 3a49ede..fb3bb9d 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd_int.c +++ b/STM32F4/cores/maple/libmaple/usbF4/STM32_USB_OTG_Driver/src/usb_dcd_int.c @@ -20,12 +20,12 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usb_dcd_int.h" +#include typedef int IRQn_Type; #define __NVIC_PRIO_BITS 4 #define __Vendor_SysTickConfig 1 -#include +#include /** @addtogroup USB_OTG_DRIVER diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/core_cm4.h b/STM32F4/cores/maple/libmaple/usbF4/VCP/core_cm4.h index 443665c..ff5e9a6 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/core_cm4.h +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/core_cm4.h @@ -141,7 +141,7 @@ #endif #include /*!< standard types definitions */ -#include /*!< Core Instruction Access */ +#include "core_cmInstr.h" /*!< Core Instruction Access */ //#include /*!< Core Function Access */ //#include /*!< Compiler specific SIMD Intrinsics */ diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/misc.c b/STM32F4/cores/maple/libmaple/usbF4/VCP/misc.c index 9f33150..15a715e 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/misc.c +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/misc.c @@ -80,7 +80,7 @@ typedef unsigned char u8; typedef int IRQn_Type; #define __NVIC_PRIO_BITS 4 #define __Vendor_SysTickConfig 1 -#include +#include "core_cm4.h" /** @addtogroup STM32F4xx_StdPeriph_Driver * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_bsp.c b/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_bsp.c index df23ccb..c365038 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_bsp.c +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_bsp.c @@ -21,13 +21,13 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usb_bsp.h" +#include #include "usbd_conf.h" -#include +#include typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; #define OTG_FS_IRQn 67 //typedef unsigned char uint8_t; -#include +#include "misc.h" //#include "stm32f4_discovery.h" @@ -97,10 +97,10 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) { // ala42 #define GPIO_AF_OTG1_FS ((uint8_t)0xA) /* OTG_FS Alternate Function mapping */ - gpio_set_mode(GPIOA,11,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); - gpio_set_mode(GPIOA,12,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); - gpio_set_af_mode(GPIOA,11,GPIO_AF_OTG1_FS) ; // OTG_FS_DM - gpio_set_af_mode(GPIOA,12,GPIO_AF_OTG1_FS) ; // OTG_FS_DP + gpio_set_mode(BOARD_USB_DM_PIN,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); + gpio_set_mode(BOARD_USB_DP_PIN,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); + gpio_set_af_mode(BOARD_USB_DM_PIN,GPIO_AF_OTG1_FS) ; // OTG_FS_DM + gpio_set_af_mode(BOARD_USB_DP_PIN,GPIO_AF_OTG1_FS) ; // OTG_FS_DP #ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED gpio_set_mode(GPIOA, 8,GPIO_MODE_AF | GPIO_OTYPE_PP | GPIO_OSPEED_100MHZ); gpio_set_af_mode(GPIOA, 8,GPIO_AF_OTG1_FS) ; // OTG_FS_SOF @@ -122,10 +122,10 @@ void USB_OTG_BSP_DeInit(USB_OTG_CORE_HANDLE *pdev) { // ala42 #define GPIO_AF0 ((uint8_t)0) /* OTG_FS Alternate Function mapping */ - gpio_set_mode(GPIOA,11, GPIO_MODE_INPUT); - gpio_set_mode(GPIOA,12, GPIO_MODE_INPUT); - gpio_set_af_mode(GPIOA,11,GPIO_AF0) ; // OTG_FS_DM - gpio_set_af_mode(GPIOA,12,GPIO_AF0) ; // OTG_FS_DP + gpio_set_mode(BOARD_USB_DM_PIN, GPIO_MODE_INPUT); + gpio_set_mode(BOARD_USB_DP_PIN, GPIO_MODE_INPUT); + gpio_set_af_mode(BOARD_USB_DM_PIN,GPIO_AF0) ; // OTG_FS_DM + gpio_set_af_mode(BOARD_USB_DP_PIN,GPIO_AF0) ; // OTG_FS_DP #ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED gpio_set_mode(GPIOA, 8,GPIO_MODE_INPUT); gpio_set_af_mode(GPIOA, 8,GPIO_AF0) ; // OTG_FS_SOF diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_conf.h b/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_conf.h index 61b0ac5..fd45f4d 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_conf.h +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usb_conf.h @@ -173,7 +173,9 @@ typedef unsigned char u8; #elif defined (__ICCARM__) /* IAR Compiler */ #define __packed __packed #elif defined ( __GNUC__ ) /* GNU Compiler */ + #ifndef __packed #define __packed __attribute__ ((__packed__)) + #endif #elif defined (__TASKING__) /* TASKING Compiler */ #define __packed __unaligned #endif /* __CC_ARM */ @@ -206,7 +208,9 @@ typedef unsigned char u8; #elif defined (__ICCARM__) /* IAR Compiler */ #define __packed __packed #elif defined ( __GNUC__ ) /* GNU Compiler */ + #ifndef __packed #define __packed __attribute__ ((__packed__)) + #endif #elif defined (__TASKING__) /* TASKING Compiler */ #define __packed __unaligned #endif /* __CC_ARM */ diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.c b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.c index b13260e..bc43747 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.c +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.c @@ -25,7 +25,6 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_cdc_vcp.h" -//#include "stm32f4_discovery.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ @@ -57,7 +56,7 @@ uint8_t UsbRecBuffer[UsbRecBufferSize]; volatile int UsbRecRead = 0; volatile int UsbRecWrite = 0; volatile int VCP_DTRHIGH = 0; -uint8_t UsbTXBlock = 0; +uint8_t UsbTXBlock = 1; uint32_t VCPBytesAvailable(void) { return (UsbRecWrite - UsbRecRead + UsbRecBufferSize) % UsbRecBufferSize; @@ -255,7 +254,7 @@ typedef struct { void systemHardReset(void) { SCB_TypeDef* rSCB = (SCB_TypeDef *) SCB_BASE; - typedef void (*funcPtr)(void); + //typedef void (*funcPtr)(void); // not used /* Reset */ rSCB->AIRCR = (u32)AIRCR_RESET_REQ; diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.h b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.h index 67475e7..1ac6c2f 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.h +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_cdc_vcp.h @@ -26,7 +26,7 @@ /* Includes ------------------------------------------------------------------*/ //#include "stm32f4xx.h" -#include "usbd_cdc_core.h" +#include #include "usbd_conf.h" diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_conf.h b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_conf.h index 516a2fb..62a40c2 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_conf.h +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_conf.h @@ -25,6 +25,7 @@ /* Includes ------------------------------------------------------------------*/ //#include "stm32f4_discovery.h" +#include "usb_conf.h" /** @defgroup USB_CONF_Exported_Defines * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.c b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.c index 537f266..e37e28c 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.c +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.c @@ -20,11 +20,11 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usbd_core.h" +#include #include "usbd_desc.h" -#include "usbd_req.h" +#include #include "usbd_conf.h" -#include "usb_regs.h" +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.h b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.h index ed999dc..987767f 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.h +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_desc.h @@ -25,7 +25,7 @@ #define __USB_DESC_H /* Includes ------------------------------------------------------------------*/ -#include "usbd_def.h" +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ diff --git a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_usr.c b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_usr.c index 84e8d6a..44eef15 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_usr.c +++ b/STM32F4/cores/maple/libmaple/usbF4/VCP/usbd_usr.c @@ -20,8 +20,8 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "usbd_usr.h" -#include "usbd_ioreq.h" +#include +#include /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY diff --git a/STM32F4/cores/maple/libmaple/usbF4/usb.c b/STM32F4/cores/maple/libmaple/usbF4/usb.c index 2c0672f..3e92186 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/usb.c +++ b/STM32F4/cores/maple/libmaple/usbF4/usb.c @@ -1,27 +1,30 @@ -#include "usbd_cdc_core.h" -#include "usbd_usr.h" -#include "usbd_desc.h" +#ifndef _USBF4_USB_H_ +#define _USBF4_USB_H_ + + +#include +#include +#include #include "usb.h" -#include -#include -#include +#include +#include +#include +#include USB_OTG_CORE_HANDLE USB_OTG_dev; -void setupUSB (void) { - #define USB_DISC_DEV GPIOD - #define USB_DISC_PIN 11 - - gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_OD); // ala42 +void setupUSB (void) +{ + gpio_set_mode(BOARD_USB_DP_PIN, GPIO_OUTPUT_OD); // ala42 #ifdef USB_DISC_OD //gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_OD); // ala42 #else //gpio_set_mode(USB_DISC_DEV, USB_DISC_PIN, GPIO_OUTPUT_PP); // ala42 for active pull-up on disconnect pin #endif - gpio_write_bit(USB_DISC_DEV, USB_DISC_PIN,0); // ala42 + gpio_clear_pin(BOARD_USB_DP_PIN); // ala42 delay_us(200000); /* setup the apb1 clock for USB */ @@ -29,7 +32,7 @@ void setupUSB (void) { //pRCC->APB1ENR |= RCC_APB1ENR_USBEN; /* initialize the usb application */ - gpio_write_bit(USB_DISC_DEV, USB_DISC_PIN, 1); // ala42 // presents us to the host + gpio_set_pin(BOARD_USB_DP_PIN); // ala42 // presents us to the host USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, @@ -93,7 +96,7 @@ RESULT usbPowerOff(void) { void usbDsbISR(void) {}; -#include "usb_dcd_int.h" +#include void __irq_OTG_FS_IRQHandler(void) { USBD_OTG_ISR_Handler (&USB_OTG_dev); @@ -102,3 +105,5 @@ void __irq_OTG_FS_IRQHandler(void) void x__irq_usbwakeup(void) { } + +#endif diff --git a/STM32F4/cores/maple/libmaple/usbF4/usb.h b/STM32F4/cores/maple/libmaple/usbF4/usb.h index f09f2bd..7f0b2aa 100644 --- a/STM32F4/cores/maple/libmaple/usbF4/usb.h +++ b/STM32F4/cores/maple/libmaple/usbF4/usb.h @@ -5,7 +5,7 @@ extern "C" { #endif -#include "usb_conf.h" +#include typedef enum _RESULT { diff --git a/STM32F4/cores/maple/libmaple/util.c b/STM32F4/cores/maple/libmaple/util.c index 8c03e18..8a745e8 100644 --- a/STM32F4/cores/maple/libmaple/util.c +++ b/STM32F4/cores/maple/libmaple/util.c @@ -128,7 +128,7 @@ void throb(void) { uint32 TOP_CNT = 0x0800; uint32 i = 0; - gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_OUTPUT_PP); + gpio_set_mode(ERROR_LED_PIN, GPIO_OUTPUT_PP); /* Error fade. */ while (1) { if (CC == TOP_CNT) { @@ -143,9 +143,9 @@ void throb(void) { } if (i < CC) { - gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 1); + gpio_set_pin(ERROR_LED_PIN); } else { - gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 0); + gpio_clear_pin(ERROR_LED_PIN); } i++; } diff --git a/STM32F4/cores/maple/libmaple/util.h b/STM32F4/cores/maple/libmaple/util.h index 62ad8af..c5ed2de 100644 --- a/STM32F4/cores/maple/libmaple/util.h +++ b/STM32F4/cores/maple/libmaple/util.h @@ -29,11 +29,12 @@ * @brief Miscellaneous utility macros and procedures. */ -#include "libmaple_types.h" - #ifndef _UTIL_H_ #define _UTIL_H_ +#include "libmaple_types.h" +#include "delay.h" + #ifdef __cplusplus extern "C"{ #endif diff --git a/STM32F4/cores/maple/new.cpp b/STM32F4/cores/maple/new.cpp new file mode 100644 index 0000000..7553ddf --- /dev/null +++ b/STM32F4/cores/maple/new.cpp @@ -0,0 +1,35 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +void *operator new(size_t size) { + return malloc(size); +} + +void *operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void * ptr) { + free(ptr); +} + +void operator delete[](void * ptr) { + free(ptr); +} diff --git a/STM32F4/cores/maple/pwm.cpp b/STM32F4/cores/maple/pwm.cpp index 1806348..c5f2ccb 100644 --- a/STM32F4/cores/maple/pwm.cpp +++ b/STM32F4/cores/maple/pwm.cpp @@ -28,8 +28,8 @@ * @brief Arduino-style PWM implementation. */ -#include "libmaple_types.h" -#include "timer.h" +#include +#include #include "boards.h" #include "pwm.h" diff --git a/STM32F4/cores/maple/usb_serial.cpp b/STM32F4/cores/maple/usb_serial.cpp index cc726c2..1764e86 100644 --- a/STM32F4/cores/maple/usb_serial.cpp +++ b/STM32F4/cores/maple/usb_serial.cpp @@ -33,21 +33,28 @@ #include "wirish.h" #include "usb.h" +#ifdef SERIAL_USB + #define USB_TIMEOUT 50 +bool USBSerial::_hasBegun = false; USBSerial::USBSerial(void) { } void USBSerial::begin(void) { + if (_hasBegun) + return; + _hasBegun = true; setupUSB(); } void USBSerial::begin(int) { - setupUSB(); + this->begin(); } void USBSerial::end(void) { disableUSB(); + _hasBegun = false; } size_t USBSerial::write(uint8 ch) { @@ -132,7 +139,7 @@ uint8 USBSerial::pending(void) { return usbGetPending(); } -uint8 USBSerial::isConnected(void) { +USBSerial::operator bool() { return usbIsConnected() && usbIsConfigured(); } @@ -153,3 +160,5 @@ void USBSerial::disableBlockingTx(void) { } USBSerial SerialUSB; + +#endif diff --git a/STM32F4/cores/maple/usb_serial.h b/STM32F4/cores/maple/usb_serial.h index a551e9d..2288025 100644 --- a/STM32F4/cores/maple/usb_serial.h +++ b/STM32F4/cores/maple/usb_serial.h @@ -33,6 +33,8 @@ #include "Stream.h" +#ifdef SERIAL_USB + /** * @brief Virtual serial terminal. */ @@ -57,14 +59,26 @@ public: uint8 getRTS(); uint8 getDTR(); - uint8 isConnected(); + operator bool(); + uint8 isConnected() { return (bool) *this; } uint8 pending(); void enableBlockingTx(void); void disableBlockingTx(void); + +protected: + static bool _hasBegun; }; extern USBSerial SerialUSB; +#define Serial SerialUSB -#endif +#else // _USB_SERIAL_H_ + +#define Serial Serial1 + +#endif // SERIAL_USB + + +#endif // _USB_SERIAL_H_ diff --git a/STM32F4/cores/maple/wirish.h b/STM32F4/cores/maple/wirish.h index 4aca74c..945e8fb 100644 --- a/STM32F4/cores/maple/wirish.h +++ b/STM32F4/cores/maple/wirish.h @@ -34,9 +34,9 @@ #define _WIRISH_H_ #include -#include "libmaple.h" +#include +#include -#include "wirish_types.h" #include "boards.h" #include "io.h" #include "bits.h" @@ -44,10 +44,8 @@ #include "ext_interrupts.h" #include "wirish_debug.h" #include "wirish_math.h" -#include "wirish_time.h" #include -#include "HardwareSPI.h" -#include "HardwareSerial.h" +#include #include "HardwareTimer.h" #include "usb_serial.h" @@ -55,9 +53,10 @@ #define HIGH 0x1 #define LOW 0x0 -#define true 0x1 -#define false 0x0 - +#ifndef true + #define true 0x1 + #define false 0x0 +#endif #define lowByte(w) ((w) & 0xFF) #define highByte(w) (((w) >> 8) & 0xFF) diff --git a/STM32F4/cores/maple/wirish_analog.cpp b/STM32F4/cores/maple/wirish_analog.cpp index 63b5eb2..4e920e7 100644 --- a/STM32F4/cores/maple/wirish_analog.cpp +++ b/STM32F4/cores/maple/wirish_analog.cpp @@ -28,9 +28,7 @@ * @brief Arduino-compatible ADC implementation. */ -#include "libmaple.h" #include "wirish.h" -#include "io.h" /* Assumes that the ADC has been initialized and that the pin is set * to INPUT_ANALOG */ diff --git a/STM32F4/cores/maple/wirish_constants.h b/STM32F4/cores/maple/wirish_constants.h index 06a85ae..f39c077 100644 --- a/STM32F4/cores/maple/wirish_constants.h +++ b/STM32F4/cores/maple/wirish_constants.h @@ -1,5 +1,5 @@ -#ifndef _WIRING_CONSTANTS_ -#define _WIRING_CONSTANTS_ +#ifndef _WIRISH_CONSTANTS_H_ +#define _WIRISH_CONSTANTS_H_ #ifdef __cplusplus extern "C"{ diff --git a/STM32F4/cores/maple/wirish_debug.h b/STM32F4/cores/maple/wirish_debug.h index d4c0bab..d7dea23 100644 --- a/STM32F4/cores/maple/wirish_debug.h +++ b/STM32F4/cores/maple/wirish_debug.h @@ -24,6 +24,9 @@ * SOFTWARE. *****************************************************************************/ +#ifndef _WIRISH_DEBUG_H_ +#define _WIRISH_DEBUG_H_ + /** * @file wirish_debug.h * @brief High level debug port configuration @@ -50,5 +53,7 @@ static inline void disableDebugPorts(void) { * @see disableDebugPorts() */ static inline void enableDebugPorts(void) { - afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); + afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY); //AFIO_DEBUG_FULL_SWJ); } + +#endif diff --git a/STM32F4/cores/maple/wirish_digital.cpp b/STM32F4/cores/maple/wirish_digital.cpp index a8b3ad8..4a65619 100644 --- a/STM32F4/cores/maple/wirish_digital.cpp +++ b/STM32F4/cores/maple/wirish_digital.cpp @@ -29,7 +29,7 @@ */ #include "wirish.h" -#include "io.h" + void pinMode(uint8 pin, WiringPinMode mode) { gpio_pin_mode outputMode; @@ -72,7 +72,7 @@ void pinMode(uint8 pin, WiringPinMode mode) { return; } - gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); + gpio_set_mode(pin, outputMode); if (PIN_MAP[pin].timer_device != NULL) { /* Enable/disable timer channels if we're switching into or @@ -84,48 +84,51 @@ void pinMode(uint8 pin, WiringPinMode mode) { } -uint32 digitalRead(uint8 pin) { +uint32 digitalRead(uint8 pin) +{ if (pin >= BOARD_NR_GPIO_PINS) { return 0; } - return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ? + return gpio_read_pin(pin) ? HIGH : LOW; } -void digitalWrite(uint8 pin, uint8 val) { +void digitalWrite(uint8 pin, uint8 val) +{ if (pin >= BOARD_NR_GPIO_PINS) { return; } - gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val); + gpio_write_pin(pin, val); } -void togglePin(uint8 pin) { +void togglePin(uint8 pin) +{ if (pin >= BOARD_NR_GPIO_PINS) { return; } - gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit); + gpio_toggle_pin(pin); } #define BUTTON_DEBOUNCE_DELAY 1 -uint8 isButtonPressed() { - if (digitalRead(BOARD_BUTTON_PIN)) { +uint8 isButtonPressed(uint8_t button) { + if (digitalRead(button)) { delay(BUTTON_DEBOUNCE_DELAY); - while (digitalRead(BOARD_BUTTON_PIN)) + while (digitalRead(button)) ; return true; } return false; } -uint8 waitForButtonPress(uint32 timeout) { +uint8 waitForButtonPress(uint8_t button, uint32 timeout) { uint32 start = millis(); uint32 time; if (timeout == 0) { - while (!isButtonPressed()) + while (!isButtonPressed(button)) ; return true; } @@ -136,6 +139,6 @@ uint8 waitForButtonPress(uint32 timeout) { time - start > timeout) { return false; } - } while (!isButtonPressed()); + } while (!isButtonPressed(button)); return true; } diff --git a/STM32F4/cores/maple/wirish_math.h b/STM32F4/cores/maple/wirish_math.h index a85b30a..1510273 100644 --- a/STM32F4/cores/maple/wirish_math.h +++ b/STM32F4/cores/maple/wirish_math.h @@ -29,8 +29,8 @@ * @brief Includes ; provides Arduino-compatible math routines. */ -#ifndef _WIRING_MATH_H_ -#define _WIRING_MATH_H_ +#ifndef _WIRISH_MATH_H_ +#define _WIRISH_MATH_H_ #include @@ -78,11 +78,12 @@ long random(long min, long max); * @param toEnd the end of the value's mapped range. * @return the mapped value. */ -static inline long map(long value, long fromStart, long fromEnd, - long toStart, long toEnd) { - return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) + - toStart; -} + // Fix by Pito 9/2017 + static inline int32_t map(int32_t value, int32_t fromStart, int32_t fromEnd, + int32_t toStart, int32_t toEnd) { + return ((int64_t)(value - fromStart) * (toEnd - toStart)) / (fromEnd - fromStart) + + toStart; + } #define PI 3.1415926535897932384626433832795 #define HALF_PI 1.5707963267948966192313216916398 @@ -148,4 +149,11 @@ double sqrt(double x); */ double pow(double x, double y); +inline uint16_t makeWord( uint16_t w ) { return w; } + +inline uint16_t makeWord( uint8_t h, uint8_t l ) { return (h << 8) | l; } + +#define word(...) makeWord(__VA_ARGS__) + + #endif diff --git a/STM32F4/cores/maple/wirish_time.cpp b/STM32F4/cores/maple/wirish_time.cpp index 270da28..654c1a2 100644 --- a/STM32F4/cores/maple/wirish_time.cpp +++ b/STM32F4/cores/maple/wirish_time.cpp @@ -28,10 +28,10 @@ * @brief Delay implementation. */ -#include "libmaple.h" -#include "systick.h" +#include +#include #include "wirish_time.h" -#include "delay.h" +#include void delay(unsigned long ms) { uint32 i; diff --git a/STM32F4/cores/maple/wirish_time.h b/STM32F4/cores/maple/wirish_time.h index 20a2fbf..87091a3 100644 --- a/STM32F4/cores/maple/wirish_time.h +++ b/STM32F4/cores/maple/wirish_time.h @@ -32,10 +32,13 @@ #ifndef __WIRISH_TIME_H_ #define __WIRISH_TIME_H_ -#include "libmaple.h" -#include "nvic.h" -#include "systick.h" #include "boards.h" +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif #define US_PER_MS 1000 @@ -102,4 +105,8 @@ void delay(unsigned long ms); */ void delayMicroseconds(uint32 us); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif diff --git a/STM32F4/cores/maple/wirish_types.h b/STM32F4/cores/maple/wirish_types.h index a3c260a..de685bf 100644 --- a/STM32F4/cores/maple/wirish_types.h +++ b/STM32F4/cores/maple/wirish_types.h @@ -30,14 +30,13 @@ * @brief Wirish library type definitions. */ -#include "libmaple_types.h" -#include "gpio.h" -#include "timer.h" -#include "adc.h" - #ifndef _WIRISH_TYPES_H_ #define _WIRISH_TYPES_H_ +#include +#include +#include + /** * Invalid stm32_pin_info adc_channel value. * @see stm32_pin_info @@ -48,16 +47,28 @@ * @brief Stores STM32-specific information related to a given Maple pin. * @see PIN_MAP */ +#ifdef BOARD_generic_f407v +// restructure members to build consecutive pairs typedef struct stm32_pin_info { - gpio_dev *gpio_device; /**< Maple pin's GPIO device */ - timer_dev *timer_device; /**< Pin's timer device, if any. */ - const adc_dev *adc_device; /**< ADC device, if any. */ - uint8 gpio_bit; /**< Pin's GPIO port bit. */ + const gpio_dev * gpio_device; /**< Maple pin's GPIO device */ + timer_dev * timer_device; /**< Pin's timer device, if any. */ uint8 timer_channel; /**< Timer channel, or 0 if none. */ uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */ - uint8 filler; + const adc_dev *adc_device; /**< ADC device, if any. */ } stm32_pin_info; +#else + +typedef struct stm32_pin_info { + const gpio_dev *gpio_device; /**< Maple pin's GPIO device */ + timer_dev *timer_device; /**< Pin's timer device, if any. */ + const adc_dev *adc_device; /**< ADC device, if any. */ + uint8 timer_channel; /**< Timer channel, or 0 if none. */ + uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */ +} stm32_pin_info; + +#endif + /** * Variable attribute, instructs the linker to place the marked * variable in Flash instead of RAM. */ diff --git a/STM32F4/libraries/RTClock/examples/Test_RTClock/Test_RTClock.ino b/STM32F4/libraries/RTClock/examples/Test_RTClock/Test_RTClock.ino new file mode 100644 index 0000000..ec6afa4 --- /dev/null +++ b/STM32F4/libraries/RTClock/examples/Test_RTClock/Test_RTClock.ino @@ -0,0 +1,209 @@ +/* + This is an example of how to use the RTclock of STM32F4 device + + This example can also be used to set the RTC to the current epoch time: + - goto: http://www.unixtimestamp.com/ + - enter the current date and time to the right field "Timestamp converter" + - press the "Convert" button + - +*/ + +#include + +#include + + +//RTClock rt(RTCSEL_LSE); // initialise +RTClock rtc; + +time_t tt; +tm_t tm; + +const uint32_t DEFAULT_TIME = 1498944019; // 2017.07.01, 21:20:19 used as reference epoch time + +#define TIME_HEADER 'T' // Header tag for serial time sync message +#define TIME_REQUEST 7 // ASCII bell character requests a time sync message + +#define LED_PIN BOARD_LED_PIN + +//----------------------------------------------------------------------------- +void blink () +{ + digitalWrite(LED_PIN, digitalRead(LED_PIN)?LOW:HIGH); +} + +uint8_t s[20]; // for serial parsing + +//----------------------------------------------------------------------------- +char * read_line() +{ + while ( Serial.available() ) Serial.read(); // empty Rx buffer + while ( Serial.available()<=0 ) ; // wait for new characters + uint8_t c, i = 0; + s[0] = 0; + while ( Serial.available() && (i<20) ) { + c = Serial.read(); + if ( c=='\n' || c== '\r') { + s[i] = 0; + break; + } + s[i++] = c; + } + while ( Serial.available() ) Serial.read(); // flush Rx + return (char*)&s[0]; +} + +//----------------------------------------------------------------------------- +void processSyncMessage(void) +{ + if ( Serial.available() ) { + if( *read_line()==(TIME_HEADER) ) { + uint32_t pctime = atoi((const char*)&s[1]); + Serial << ("Epoch time received: ") << pctime << endl; + if ( pctime >= DEFAULT_TIME) { // check the integer is a valid epoch time + rtc.setTime(pctime); // Set RTC to the time received via the serial port + } + } + Serial << endl; + } +} + +//----------------------------------------------------------------------------- +void Change_DateTime(void) +{ + // check and correct the weekday if necessary + rtc.getTime(tm); + Serial << "Current weekday is " << (tm.weekday); + // get time elements + tt = rtc.makeTime(tm); + uint16_t tmp = rtc.weekday(tt); + if ( tmp!=tm.weekday ) {// correct weekday + rtc.setTime(tt); + Serial << " instead of " << tmp << ". Now is corrected.\n"; + } else { + Serial << " - seems to be fine, no need to change it.\n"; + } + + uint8_t chg = 0; + // get time elements + rtc.getTime(tm); + Serial << "\nCurrent RTC date: " << (1970+tm.year) << "." << (tm.month) << (".") << (tm.day) << (", weekday: ") << (tm.weekday) << endl; + Serial << "Do you want to change it? (y/n)\n"; + if ( *read_line()=='y' ) { + // change here the date +change_year: + Serial << "Current year: " << (1970+tm.year) << ". Enter new year in \"YYYY\" format (numbers only) or press enter to skip.\n"; + if (*read_line()==0) goto change_month; + tmp = atoi((const char*)s); + if ( tmp<1970 ) { Serial << "Please enter a valid number greater than 1970\n"; goto change_year; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_year; + tm.year = tmp-1970; + chg = 1; +change_month: + Serial << "Current month: " << tm.month << ". Enter new month in \"MM\" format [1..12] or press enter to skip.\n"; + if (*read_line()==0) goto change_day; + tmp = atoi((const char*)s); + if ( tmp<1 || tmp>12 ) { Serial << "Please enter a valid number [1..12]\n"; goto change_month; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_month; + tm.month = tmp; + chg = 1; +change_day: + Serial << "Current day: " << tm.day << ". Enter new day in \"DD\" format [1..31] or press enter to skip.\n"; + if (*read_line()==0) goto change_weekday; + tmp = atoi((const char*)s); + if ( tmp<1 || tmp>31 ) { Serial << "Please enter a valid number [1..31]\n"; goto change_day; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_day; + tm.day = tmp; + chg = 1; +change_weekday: + Serial << "Current weekday: " << tm.weekday << ". Enter new weekday [1(=Monday)..7(=Sunday)] or press enter to skip.\n"; + if (*read_line()==0) goto change_time; + tmp = atoi((const char*)s); + if ( tmp<1 || tmp>7 ) { Serial << "Please enter a valid number [1..7]\n"; goto change_weekday; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_weekday; + tm.weekday = tmp; + chg = 1; +change_time: + Serial << "Current RTC time: " << _TIME(tm.hour, tm.minute, tm.second) << endl; + Serial << "Do you want to change it? (y/n)\n"; + if ( *read_line()=='n' ) goto change_end; +change_hour: + Serial << "Current hour: " << tm.hour << ". Enter new hour [0..23] or press enter to skip.\n"; + if (*read_line()==0) goto change_minute; + tmp = atoi((const char*)s); + if ( tmp>23 ) { Serial << "Please enter a valid number [0..23]\n"; goto change_hour; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_hour; + tm.hour = tmp; + chg = 1; +change_minute: + Serial << "Current minute: " << tm.minute << ". Enter new minute [0..59] or press enter to skip.\n"; + if (*read_line()==0) goto change_second; + tmp = atoi((const char*)s); + if ( tmp>59 ) { Serial << "Please enter a valid number [0..59]\n"; goto change_minute; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_minute; + tm.minute = tmp; + chg = 1; +change_second: + Serial << "Current second: " << tm.second << ". Enter new second [0..59] or press enter to skip.\n"; + if (*read_line()==0) goto change_end; + tmp = atoi((const char*)s); + if ( tmp>59 ) { Serial << "Please enter a valid number [0..59]\n"; goto change_second; } + Serial << "You entered: " << tmp << ". Accept value? (y/n)\n"; + if ( *read_line()=='n' ) goto change_second; + tm.second = tmp; + chg = 1; + } else { + goto change_time; + } + +change_end: + if ( chg ) { + // set here the RTC time. + Serial << "Changed date & time: " << (1970+tm.year) << "." << (tm.month) << (".") << (tm.day) << (", weekday: ") << (tm.weekday) << ", " << _TIME(tm.hour, tm.minute, tm.second) << endl; + Serial << "Write now to RTC? (y/n)\n"; + read_line(); + if ( s[0]=='y' ) { + rtc.setTime(tm); + Serial << "Data written to RTC.\n\n"; + } + } else + Serial << "RTC was not changed.\n\n"; +} +//----------------------------------------------------------------------------- +void setup() +{ + Serial.begin(); + delay(3000); + + pinMode(LED_PIN, OUTPUT); + + Serial << "This is an example of how to use the STM32F4 RTC library.\n\n"; + + Change_DateTime(); +} + +//----------------------------------------------------------------------------- +void loop() +{ + if ( Serial.available() ) { + // adjust time according to received epoch time from PC + processSyncMessage(); + } + + if (tt!=rtc.now()) { + // get epoch time + tt = rtc.now(); + Serial << ("- RTC epoch timestamp = ") << (tt); + // get time elements + rtc.getTime(tm); + //rtc.breakTime(tt, tm); + Serial << (" == ") << (1970+tm.year) << "." << (tm.month) << (".") << (tm.day) << (", weekday ") << (tm.weekday) << (", "); + Serial << _TIME(tm.hour, tm.minute, tm.second) << endl; + } +} \ No newline at end of file diff --git a/STM32F4/libraries/RTClock/library.properties b/STM32F4/libraries/RTClock/library.properties index 5a5e4b7..a8878f6 100644 --- a/STM32F4/libraries/RTClock/library.properties +++ b/STM32F4/libraries/RTClock/library.properties @@ -7,3 +7,4 @@ paragraph=Real Time Clock for STM32F4 category=Other url= architectures=STM32F4 +maintainer=www.stm32duino.com diff --git a/STM32F4/libraries/RTClock/src/RTClock.cpp b/STM32F4/libraries/RTClock/src/RTClock.cpp index ee82c95..a6ef9f1 100644 --- a/STM32F4/libraries/RTClock/src/RTClock.cpp +++ b/STM32F4/libraries/RTClock/src/RTClock.cpp @@ -42,15 +42,7 @@ voidFuncPtr handlerAlarmA = NULL; voidFuncPtr handlerAlarmB = NULL; voidFuncPtr handlerPeriodicWakeup = NULL; - -RTClock::RTClock() { - RTClock(RTCSEL_HSE, 7999, 124); -} - -RTClock::RTClock(rtc_clk_src src) { - RTClock(src, 0, 0); -} - +//----------------------------------------------------------------------------- RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler) { uint32 t = 0; RCC_BASE->APB1ENR |= RCC_APB1RSTR_PWRRST; @@ -144,117 +136,155 @@ RTClock::~RTClock() { } */ -void RTClock::setTime (time_t time_stamp) { - unsigned char years = 0; - unsigned char months = 0; - unsigned char monthLength = 0; - unsigned char wdays = 0; - unsigned char hours = 0; - unsigned char mins = 0; - unsigned char secs = 0; - unsigned long days; +//----------------------------------------------------------------------------- +void RTClock::setTime (time_t time_stamp) +{ + breakTime(time_stamp, tm); // time will be broken to tm + setTime(tm); +} - secs = time_stamp % 60; - time_stamp /= 60; // now it is minutes - mins = time_stamp % 60; - time_stamp /= 60; // now it is hours - hours = time_stamp % 24; - time_stamp /= 24; // now it is days - wdays = ((time_stamp + 4) % 7) + 1; // Sunday is day 1 - - while((unsigned)(days += (LEAP_YEAR(years) ? 366 : 365)) <= time_stamp) { - years++; - } - - days -= LEAP_YEAR(years) ? 366 : 365; - time_stamp -= days; // now it is days in this year, starting at 0 - - for (months = 0; months < 12; months++) { - if (months == 1) { // february - if (LEAP_YEAR(years)) { - monthLength = 29; - } else { - monthLength = 28; - } - } else { - monthLength = monthDays[months]; - } - - if (time_stamp >= monthLength) { - time_stamp -= monthLength; - } else { - break; - } - } - months++; // jan is month 1 - days = time_stamp + 1; // day of month +//----------------------------------------------------------------------------- +void RTClock::setTime (tm_t & tm) +{ + if (tm.year > 99) + tm.year = tm.year % 100; rtc_enter_config_mode(); - RTC_BASE->TR = ((hours / 10) << 20) | ((hours % 10) << 16) | ((mins / 10) << 12) | ((mins % 10) << 8) | ((secs / 10) << 4) | (secs % 10); - RTC_BASE->DR = ((years / 10) << 20) | ((years % 10) << 16) | (wdays << 13) | ((months / 10) << 12) | ((months % 10) << 8) | ((days / 10) << 4) | (days % 10); + RTC_BASE->TR = BUILD_TIME_REGISTER(tm.hour, tm.minute, tm.second); + RTC_BASE->DR = BUILD_DATE_REGISTER(tm.year, tm.month, tm.day, tm.weekday); rtc_exit_config_mode(); } - -void RTClock::setTime (struct tm* tm_ptr) { - rtc_enter_config_mode(); - if (tm_ptr->tm_year > 99) - tm_ptr->tm_year = tm_ptr->tm_year % 100; - tm_ptr->tm_wday = tm_ptr->tm_wday & 0x7; - RTC_BASE->TR = ((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) | - ((tm_ptr->tm_min / 10) << 12) | ((tm_ptr->tm_min % 10) << 8) | - ((tm_ptr->tm_sec / 10) << 4) | (tm_ptr->tm_sec % 10); - RTC_BASE->DR = ((tm_ptr->tm_year / 10) << 20) | ((tm_ptr->tm_year % 10) << 16) | (tm_ptr->tm_wday << 13) | - ((tm_ptr->tm_mon / 10) << 12) | ((tm_ptr->tm_mon % 10) << 8) | - ((tm_ptr->tm_mday / 10) << 4) | (tm_ptr->tm_mday % 10); - rtc_exit_config_mode(); -} - -time_t RTClock::getTime() { - uint32 dr_reg = RTC_BASE->DR; - uint32 tr_reg = RTC_BASE->TR; - int years = 10 * ((dr_reg & 0x00F00000) >> 20) + ((dr_reg & 0x000F0000) >> 16); - int months = 10 * ((dr_reg & 0x00001000) >> 12) + ((dr_reg & 0x00000F00) >> 8); - int days = 10 * ((dr_reg & 0x00000030) >> 4) + (dr_reg & 0x000000F); - int hours = 10 * ((tr_reg & 0x00300000) >> 20) + ((tr_reg & 0x000F0000) >> 16); - int mins = 10 * ((tr_reg & 0x00007000) >> 12) + ((tr_reg & 0x0000F00) >> 8); - int secs = 10 * ((tr_reg & 0x00000070) >> 4) + (tr_reg & 0x0000000F); - // seconds from 1970 till 1 jan 00:00:00 of the given year - time_t t = (years + 30) * SECS_PER_DAY * 365; - for (int i = 0; i < (years + 30); i++) { - if (LEAP_YEAR(i)) { - t += SECS_PER_DAY; // add extra days for leap years + +/*============================================================================*/ +/* functions to convert to and from system time */ +/* These are for interfacing with time serivces and are not normally needed in a sketch */ + +// leap year calulator expects year argument as years offset from 1970 +#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) + +//static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 + +//----------------------------------------------------------------------------- +void RTClock::breakTime(time_t timeInput, tm_t & tm) +{ +// break the given time_t into time components +// this is a more compact version of the C library localtime function +// note that year is offset from 1970 !!! + + uint8_t year; + uint8_t month, monthLength; + uint32_t time; + uint32_t days; + + time = (uint32_t)timeInput; + tm.second = time % 60; + time /= 60; // now it is minutes + tm.minute = time % 60; + time /= 60; // now it is hours + tm.hour = time % 24; + time /= 24; // now it is days + tm.weekday = ((time + 4) % 7); // Monday is day 1 // + 1; // Sunday is day 1 + + year = 0; + days = 0; + while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { + year++; } - } - // add days for this year, months start from 1 - for (int i = 1; i < months; i++) { - if ( (i == 2) && LEAP_YEAR(years)) { - t += SECS_PER_DAY * 29; - } else { - t += SECS_PER_DAY * monthDays[i - 1]; //monthDays array starts from 0 + tm.year = year; // year is offset from 1970 + + days -= LEAP_YEAR(year) ? 366 : 365; + time -= days; // now it is days in this year, starting at 0 + + days = 0; + month = 0; + monthLength = 0; + for (month=0; month<12; month++) { + if (month==1) { // february + if (LEAP_YEAR(year)) { + monthLength=29; + } else { + monthLength=28; + } + } else { + monthLength = monthDays[month]; + } + + if (time >= monthLength) { + time -= monthLength; + } else { + break; + } } - } - t += (days - 1) * SECS_PER_DAY + hours * SECS_PER_HOUR + mins * SECS_PER_MIN + secs; - return t; + tm.month = month + 1; // jan is month 1 + tm.day = time + 1; // day of month } - -struct tm* RTClock::getTime(struct tm* tm_ptr) { - uint32 dr_reg = RTC_BASE->DR; - uint32 tr_reg = RTC_BASE->TR; - tm_ptr->tm_year = 10 * ((dr_reg & 0x00F00000) >> 20) + ((dr_reg & 0x000F0000) >> 16); - tm_ptr->tm_mon = 10 * ((dr_reg & 0x00001000) >> 12) + ((dr_reg & 0x00000F00) >> 8); - tm_ptr->tm_mday = 10 * ((dr_reg & 0x00000030) >> 4) + (dr_reg & 0x000000F); - tm_ptr->tm_hour = 10 * ((tr_reg & 0x00300000) >> 20) + ((tr_reg & 0x000F0000) >> 16); - tm_ptr->tm_min = 10 * ((tr_reg & 0x00007000) >> 12) + ((tr_reg & 0x0000F00) >> 8); - tm_ptr->tm_sec = 10 * ((tr_reg & 0x00000070) >> 4) + (tr_reg & 0x0000000F); - return tm_ptr; + +//----------------------------------------------------------------------------- +time_t RTClock::makeTime(tm_t & tm) +{ +// assemble time elements into time_t +// note year argument is offset from 1970 (see macros in time.h to convert to other formats) +// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 + + int i; + uint32_t seconds; + + // seconds from 1970 till 1 jan 00:00:00 of the given year + seconds = tm.year*(SECS_PER_DAY * 365); + for (i = 0; i < tm.year; i++) { + if (LEAP_YEAR(i)) { + seconds += SECS_PER_DAY; // add extra days for leap years + } + } + + // add days for this year, months start from 1 + for (i = 1; i < tm.month; i++) { + if ( (i == 2) && LEAP_YEAR(tm.year)) { + seconds += SECS_PER_DAY * 29; + } else { + seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 + } + } + seconds+= (tm.day-1) * SECS_PER_DAY; + seconds+= tm.hour * SECS_PER_HOUR; + seconds+= tm.minute * SECS_PER_MIN; + seconds+= tm.second; + return (time_t)seconds; } - -void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) { + +//----------------------------------------------------------------------------- +void RTClock::getTime(tm_t & tm) +{ + uint32_t dr_reg, tr_reg; + do { // read multiple time till both readings are equal + dr_reg = getDReg(); + tr_reg = getTReg(); + } while ( (dr_reg!=getDReg()) || (tr_reg!=getTReg()) ); + tm.year = _year(dr_reg); + tm.month = _month(dr_reg); + tm.day = _day(dr_reg); + tm.weekday = _weekday(dr_reg); + tm.pm = _pm(tr_reg); + tm.hour = _hour(tr_reg); + tm.minute = _minute(tr_reg); + tm.second = _second(tr_reg); +} + +//----------------------------------------------------------------------------- +time_t RTClock::getTime() +{ + getTime(tm); + return makeTime(tm); +} + +//----------------------------------------------------------------------------- +void RTClock::setAlarmATime (tm_t * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) +{ uint32 t = 0; rtc_enter_config_mode(); - unsigned int bits = ((tm_ptr->tm_mday / 10) << 28) | ((tm_ptr->tm_mday % 10) << 24) | - ((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) | - ((tm_ptr->tm_min / 10) << 12) | ((tm_ptr->tm_min % 10) << 8) | - ((tm_ptr->tm_sec / 10) << 4) | (tm_ptr->tm_sec % 10); + unsigned int bits = ((tm_ptr->day / 10) << 28) | ((tm_ptr->day % 10) << 24) | + ((tm_ptr->hour / 10) << 20) | ((tm_ptr->hour % 10) << 16) | + ((tm_ptr->minute / 10) << 12) | ((tm_ptr->minute % 10) << 8) | + ((tm_ptr->second / 10) << 4) | (tm_ptr->second % 10); if (!date_match) bits |= (1 << 31); if (!hours_match) bits |= (1 << 23); if (!mins_match) bits |= (1 << 15); @@ -276,27 +306,30 @@ void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, boo rtc_enable_alarm_event(); } - -void RTClock::setAlarmATime (time_t alarm_time, bool hours_match, bool mins_match, bool secs_match, bool date_match) { - struct tm* tm_ptr = gmtime(&alarm_time); - setAlarmATime(tm_ptr, hours_match, mins_match, secs_match, date_match); +//----------------------------------------------------------------------------- +void RTClock::setAlarmATime (time_t alarm_time, bool hours_match, bool mins_match, bool secs_match, bool date_match) +{ + breakTime(alarm_time, tm); + setAlarmATime(&tm, hours_match, mins_match, secs_match, date_match); } - -void RTClock::turnOffAlarmA() { +//----------------------------------------------------------------------------- +void RTClock::turnOffAlarmA(void) +{ rtc_enter_config_mode(); RTC_BASE->CR &= ~(1 << RTC_CR_ALRAIE_BIT); // turn off ALRAIE rtc_exit_config_mode(); } - -void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) { +//----------------------------------------------------------------------------- +void RTClock::setAlarmBTime (tm_t * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) +{ uint32 t = 0; rtc_enter_config_mode(); - unsigned int bits = ((tm_ptr->tm_mday / 10) << 28) | ((tm_ptr->tm_mday % 10) << 24) | - ((tm_ptr->tm_hour / 10) << 20) | ((tm_ptr->tm_hour % 10) << 16) | - ((tm_ptr->tm_min / 10) << 12) | ((tm_ptr->tm_min % 10) << 8) | - ((tm_ptr->tm_sec / 10) << 4) | (tm_ptr->tm_sec % 10); + unsigned int bits = ((tm_ptr->day / 10) << 28) | ((tm_ptr->day % 10) << 24) | + ((tm_ptr->hour / 10) << 20) | ((tm_ptr->hour % 10) << 16) | + ((tm_ptr->minute / 10) << 12) | ((tm_ptr->minute % 10) << 8) | + ((tm_ptr->second / 10) << 4) | (tm_ptr->second % 10); if (!date_match) bits |= (1 << 31); if (!hours_match) bits |= (1 << 23); if (!mins_match) bits |= (1 << 15); @@ -318,21 +351,23 @@ void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, boo rtc_enable_alarm_event(); } - -void RTClock::setAlarmBTime (time_t alarm_time, bool hours_match, bool mins_match, bool secs_match, bool date_match) { - struct tm* tm_ptr = gmtime(&alarm_time); - setAlarmBTime(tm_ptr, hours_match, mins_match, secs_match, date_match); +//----------------------------------------------------------------------------- +void RTClock::setAlarmBTime (time_t alarm_time, bool hours_match, bool mins_match, bool secs_match, bool date_match) +{ + breakTime(alarm_time, tm); + setAlarmBTime(&tm, hours_match, mins_match, secs_match, date_match); } - +//----------------------------------------------------------------------------- void RTClock::turnOffAlarmB() { rtc_enter_config_mode(); RTC_BASE->CR &= ~(1 << RTC_CR_ALRBIE_BIT); // turn off ALRBIE rtc_exit_config_mode(); } - -void RTClock::setPeriodicWakeup(uint16 period) { +//----------------------------------------------------------------------------- +void RTClock::setPeriodicWakeup(uint16 period) +{ uint32 t = 0; rtc_enter_config_mode(); RTC_BASE->CR &= ~(1 << RTC_CR_WUTE_BIT); diff --git a/STM32F4/libraries/RTClock/src/RTClock.h b/STM32F4/libraries/RTClock/src/RTClock.h index facaa00..eb2e1f6 100644 --- a/STM32F4/libraries/RTClock/src/RTClock.h +++ b/STM32F4/libraries/RTClock/src/RTClock.h @@ -1,29 +1,35 @@ -#include -#include -#include -#include -#include -#include -#include - #ifndef _RTCLOCK_H_ #define _RTCLOCK_H_ -//#define RTC_DEBUG #ifdef __cplusplus extern "C" { #endif + + +#include // for __time_t_defined +#include +#include +#include +#include +#include +#include + +//#define RTC_DEBUG + + +#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc + #warning "Using private time_t definintion" + typedef uint32_t time_t; +#endif + #ifdef RTC_DEBUG extern void dbg_printf(const char *fmt, ... ); #define rtc_debug_printf(fmt, ...) dbg_printf(fmt, ##__VA_ARGS__); #else #define rtc_debug_printf(...) #endif -#ifdef __cplusplus -} -#endif #define SECS_PER_MIN (60UL) @@ -33,32 +39,32 @@ extern "C" { #define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK) #define SECS_PER_YEAR (SECS_PER_WEEK * 52UL) #define SECS_YR_2000 (946684800UL) // the time at the start of y2k -#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) +#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) static const unsigned char monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 typedef struct rtc_reg_map { - __io uint32 TR; /**< Time register */ - __io uint32 DR; /**< Date register */ - __io uint32 CR; /**< Control register */ - __io uint32 ISR; /**< Init Status register */ - __io uint32 PRER; /**< Prescaler register */ - __io uint32 WUTR; /**< Wakeup Timer register */ - __io uint32 CALIBR; /**< Calibration register */ - __io uint32 ALRMAR; /**< Alarm A register */ - __io uint32 ALRMBR; /**< Alarm B register */ - __io uint32 WPR; /**< Write Protect register */ - __io uint32 SSR; /**< SubSecond register */ - __io uint32 SHIFTR; /**< Shift Control register */ - __io uint32 TSTR; /**< TimeStamp Time register */ - __io uint32 TSDR; /**< TimeStamp Date register */ - __io uint32 TSSSR; /**< TimeStamp SubSecond register */ - __io uint32 CALR; /**< Calibration register */ - __io uint32 TAFCR; /**< Tamper and Alternate Function Config register */ - __io uint32 ALRMASSR; /**< Alarm A subSecond register */ - __io uint32 ALRMBSSR; /**< Alarm B subSecond register */ - __io uint32 BKPxR; /**< Backup registers */ + __IO uint32 TR; /**< Time register */ + __IO uint32 DR; /**< Date register */ + __IO uint32 CR; /**< Control register */ + __IO uint32 ISR; /**< Init Status register */ + __IO uint32 PRER; /**< Prescaler register */ + __IO uint32 WUTR; /**< Wakeup Timer register */ + __IO uint32 CALIBR; /**< Calibration register */ + __IO uint32 ALRMAR; /**< Alarm A register */ + __IO uint32 ALRMBR; /**< Alarm B register */ + __IO uint32 WPR; /**< Write Protect register */ + __IO uint32 SSR; /**< SubSecond register */ + __IO uint32 SHIFTR; /**< Shift Control register */ + __IO uint32 TSTR; /**< TimeStamp Time register */ + __IO uint32 TSDR; /**< TimeStamp Date register */ + __IO uint32 TSSSR; /**< TimeStamp SubSecond register */ + __IO uint32 CALR; /**< Calibration register */ + __IO uint32 TAFCR; /**< Tamper and Alternate Function Config register */ + __IO uint32 ALRMASSR; /**< Alarm A subSecond register */ + __IO uint32 ALRMBSSR; /**< Alarm B subSecond register */ + __IO uint32 BKPxR; /**< Backup registers */ } rtc_reg_map; /** RTC register map base pointer */ @@ -91,6 +97,28 @@ typedef enum rtc_clk_src { RTCSEL_HSE = 0x13, } rtc_clk_src; +// Time register +#define RTC_TR_PM_BIT 22 +#define RTC_TR_HOUR_BIT 16 +#define RTC_TR_MINUTE_BIT 8 +#define RTC_TR_SECOND_BIT 0 + +#define RTC_TR_PM_MASK (0x01)//<>4)) + (b&0x0F) ); } +static inline uint8_t bin2bcd(uint8_t b) { return ( ((b/10)<<4) + (b%10) ); } class RTClock { - public: - RTClock(); - RTClock(rtc_clk_src src ); + public: + RTClock() { RTClock(RTCSEL_LSE, 0, 0); } + RTClock(rtc_clk_src src ) { RTClock(src, 0, 0); } RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler); //~RTClock(); //to implement + + void breakTime(time_t epoch_time, tm_t & tm); + time_t makeTime(tm_t & tm); void setTime (time_t time_stamp); - void setTime (struct tm * tm_ptr); + void setTime (tm_t & tm); - struct tm* getTime(struct tm* tm_ptr); time_t getTime(); + void getTime(tm_t & tm); + + time_t now() { return getTime(); } + void now(tm_t & tmm ) { getTime(tmm); } // non-standard use of now() function, added for compatibility with previous versions of the library + + uint8_t year(void) { getTime(tm); return tm.year; } + uint8_t month(void) { getTime(tm); return tm.month; } + uint8_t day(void) { getTime(tm); return tm.day; } + uint8_t weekday(void) { getTime(tm); return tm.weekday; } + uint8_t hour(void) { getTime(tm); return tm.hour; } + uint8_t minute(void) { getTime(tm); return tm.minute; } + uint8_t second(void) { getTime(tm); return tm.second; } + //uint8_t pm(void) { return _pm(RTC_BASE->TR); } + uint8_t isPM(void) { return ( hour()>=12 ); } - void setAlarmATime (tm * tm_ptr, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false); + uint8_t year(time_t t) { breakTime(t, tm); return tm.year; } + uint8_t month(time_t t) { breakTime(t, tm); return tm.month; } + uint8_t day(time_t t) { breakTime(t, tm); return tm.day; } + uint8_t weekday(time_t t) { breakTime(t, tm); return tm.weekday; } + uint8_t hour(time_t t) { breakTime(t, tm); return tm.hour; } + uint8_t minute(time_t t) { breakTime(t, tm); return tm.minute; } + uint8_t second(time_t t) { breakTime(t, tm); return tm.second; } + uint8_t isPM(time_t t) { return (hour(t)>=12); } + + void setAlarmATime (tm_t * tm_ptr, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false); void setAlarmATime (time_t alarm_time, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false); void turnOffAlarmA(); - void setAlarmBTime (tm * tm_ptr, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false); + void setAlarmBTime (tm_t * tm_ptr, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false); void setAlarmBTime (time_t alarm_time, bool hours_match = true, bool mins_match = true, bool secs_match = true, bool date_match = false); void turnOffAlarmB(); @@ -143,17 +218,29 @@ class RTClock { void attachPeriodicWakeupInterrupt(voidFuncPtr function); void detachPeriodicWakeupInterrupt(); + inline void attachSecondsInterrupt(voidFuncPtr function) { attachPeriodicWakeupInterrupt(function); } + inline void detachSecondsInterrupt() { detachPeriodicWakeupInterrupt(); } void attachAlarmAInterrupt(voidFuncPtr function); void detachAlarmAInterrupt(); void attachAlarmBInterrupt(voidFuncPtr function); void detachAlarmBInterrupt(); - //private: - -} ; + private: + inline uint8_t _year(uint32_t dr) { return bcd2bin( (dr>>RTC_DR_YEAR_BIT) & RTC_DR_YEAR_MASK ); } + inline uint8_t _month(uint32_t dr) { return bcd2bin( (dr>>RTC_DR_MONTH_BIT) & RTC_DR_MONTH_MASK ); } + inline uint8_t _day(uint32_t dr) { return bcd2bin( (dr>>RTC_DR_DAY_BIT) & RTC_DR_DAY_MASK ); } + inline uint8_t _weekday(uint32_t dr) { return bcd2bin( (dr>>RTC_DR_WEEKDAY_BIT) & RTC_DR_WEEKDAY_MASK ); } + inline uint8_t _pm(uint32_t tr) { return ( (tr>>RTC_TR_PM_BIT) & RTC_TR_PM_MASK ); } + inline uint8_t _hour(uint32_t tr) { return bcd2bin( (tr>>RTC_TR_HOUR_BIT) & RTC_TR_HOUR_MASK ); } + inline uint8_t _minute(uint32_t tr) { return bcd2bin( (tr>>RTC_TR_MINUTE_BIT) & RTC_TR_MINUTE_MASK ); } + inline uint8_t _second(uint32_t tr) { return bcd2bin( (tr>>RTC_TR_SECOND_BIT) & RTC_TR_SECOND_MASK ); } + tm_t tm; +}; +inline uint32_t getTReg(void) { return (uint32_t)(RTC_BASE->TR); } +inline uint32_t getDReg(void) { return (uint32_t)(RTC_BASE->DR); } /** * @brief Clear the register synchronized flag. The flag is then set by hardware after a write to PRL/DIV or CNT. @@ -246,7 +333,8 @@ static inline void rtc_disable_wakeup_event() { *bb_perip(&EXTI_BASE->RTSR, EXTI_RTC_WAKEUP_BIT) = 0; } - +#ifdef __cplusplus +} +#endif #endif // _RTCLOCK_H_ - \ No newline at end of file diff --git a/STM32F4/libraries/SDIO/SdioF4.cpp b/STM32F4/libraries/SDIO/SdioF4.cpp new file mode 100644 index 0000000..63c928a --- /dev/null +++ b/STM32F4/libraries/SDIO/SdioF4.cpp @@ -0,0 +1,820 @@ +/* Arduino SdCard Library + * Copyright (C) 2016 by William Greiman + * + * This file is part of the Arduino SdSpiCard Library + * + * This Library 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 3 of the License, or + * (at your option) any later version. + * + * This Library 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 the Arduino SdSpiCard Library. If not, see + * . + */ + +#include "SdioF4.h" +#include +#include +#include + +#define USE_DEBUG_MODE 0 +#define USE_YIELD 0 + +//============================================================================== +//#define SDHC_PROCTL_DTW_4BIT 0x01 +#define CMD8_RETRIES 10 +#define BUSY_TIMEOUT_MILLIS 750 +//============================================================================== +#define CMD_RESP_NONE SDIO_CMD_WAIT_NO_RESP +#define CMD_RESP_R1 SDIO_CMD_WAIT_SHORT_RESP // normal response +#define CMD_RESP_R1b SDIO_CMD_WAIT_SHORT_RESP // normal response + busy data line (optional) +#define CMD_RESP_R2 SDIO_CMD_WAIT_LONG_RESP // CID, CSD +#define CMD_RESP_R3 SDIO_CMD_WAIT_SHORT_RESP // OCR register, response to ACMD41 +#define CMD_RESP_R6 SDIO_CMD_WAIT_SHORT_RESP // published RCA response, response to CMD3 +#define CMD_RESP_R7 SDIO_CMD_WAIT_SHORT_RESP // response to CMD8 + +#define CMD0_XFERTYP (uint16_t)( CMD0 | CMD_RESP_NONE ) +#define CMD2_XFERTYP (uint16_t)( CMD2 | CMD_RESP_R2 ) +#define CMD3_XFERTYP (uint16_t)( CMD3 | CMD_RESP_R6 ) +#define CMD6_XFERTYP (uint16_t)( CMD6 | CMD_RESP_R1 ) +#define ACMD6_XFERTYP (uint16_t)( ACMD6 | CMD_RESP_R1 ) +#define CMD7_XFERTYP (uint16_t)( CMD7 | CMD_RESP_R1b ) +#define CMD8_XFERTYP (uint16_t)( CMD8 | CMD_RESP_R7 ) +#define CMD9_XFERTYP (uint16_t)( CMD9 | CMD_RESP_R2 ) +#define CMD10_XFERTYP (uint16_t)( CMD10 | CMD_RESP_R2 ) +#define CMD12_XFERTYP (uint16_t)( CMD12 | CMD_RESP_R1b ) +#define CMD13_XFERTYP (uint16_t)( CMD13 | CMD_RESP_R1 ) +#define CMD17_XFERTYP (uint16_t)( CMD17 | CMD_RESP_R1 ) +#define CMD18_XFERTYP (uint16_t)( CMD18 | CMD_RESP_R1 ) +#define ACMD23_XFERTYP (uint16_t)( ACMD23 | CMD_RESP_R1 ) +#define CMD24_XFERTYP (uint16_t)( CMD24 | CMD_RESP_R1 ) +#define CMD25_XFERTYP (uint16_t)( CMD25 | CMD_RESP_R1 ) +#define CMD32_XFERTYP (uint16_t)( CMD32 | CMD_RESP_R1 ) +#define CMD33_XFERTYP (uint16_t)( CMD32 | CMD_RESP_R1 ) +#define CMD38_XFERTYP (uint16_t)( CMD38 | CMD_RESP_R1b ) +#define ACMD41_XFERTYP (uint16_t)( ACMD41 | CMD_RESP_R3 ) + +#define CMD55_XFERTYP (uint16_t)( CMD55 | CMD_RESP_R1 ) + +//============================================================================= +//static void enableGPIO(bool enable); +//static void enableDmaIrs(); +static void initSDHC(void); +static bool isBusyCMD13(void); +static bool isBusyTransferComplete(void); +//static bool isBusyCommandComplete(); +//static bool isBusyCommandInhibit(); +static bool readReg16(uint32_t xfertyp, void* data); +//static void setSdclk(uint32_t kHzMax); +static bool yieldTimeout(bool (*fcn)(void)); +static bool waitDmaStatus(void); +static bool waitTimeout(bool (*fcn)(void)); +//----------------------------------------------------------------------------- +#define TRX_RD 0 +#define TRX_WR 1 +static uint8_t m_dir = TRX_RD; +static bool (*m_busyFcn)() = 0; +static bool m_initDone = false; +static uint32_t m_lba; // for raw non-DMA read(write)Start, read(write)Data, read(write)Stop +static uint32_t m_cnt; // for raw non-DMA read(write)Start, read(write)Data, read(write)Stop +static bool m_version2; +static bool m_highCapacity; +static uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED; +static uint32_t m_errorLine = 0; +static uint32_t m_rca; +//static volatile bool m_dmaBusy = false; +static volatile uint32_t m_irqstat; +static uint32_t m_sdClkKhz = 0; +static uint32_t m_ocr; +static cid_t m_cid; +static csd_t m_csd; +static uint32_t t = 0; +//============================================================================= +#if USE_DEBUG_MODE +#define DBG_PRINT() { \ + Serial.write('_'); Serial.print(__FUNCTION__); Serial.write('_'); Serial.print(__LINE__); Serial.print(": "); \ + Serial.print("DMA->LISR: "); Serial.print(DMA2->regs->LISR, HEX); \ + /*Serial.print("DMA->HISR: "); Serial.println(DMA2->regs->HISR, HEX);*/ \ + Serial.print(", DMA->CR: "); Serial.print(DMA2->regs->STREAM[DMA_STREAM3].CR, HEX); \ + Serial.print(", DMA->NDTR: "); Serial.print(DMA2->regs->STREAM[DMA_STREAM3].NDTR, HEX); \ + /**/Serial.print(", DMA->PAR: "); Serial.print(DMA2->regs->STREAM[DMA_STREAM3].PAR, HEX); \ + /**/Serial.print(", DMA->M0AR: "); Serial.print(DMA2->regs->STREAM[DMA_STREAM3].M0AR, HEX); \ + Serial.print(", DMA->FCR: "); Serial.print(DMA2->regs->STREAM[DMA_STREAM3].FCR, HEX); \ + \ + /*Serial.print(" SDIO->POWER: "); Serial.println(SDIO->POWER, HEX);*/ \ + Serial.print(", SDIO->CLKCR: "); Serial.print(SDIO->CLKCR, HEX); \ + Serial.print(", SDIO->DTIMER: "); Serial.print(SDIO->DTIMER, HEX); \ + Serial.print(", SDIO->DCTRL: "); Serial.print(SDIO->DCTRL, HEX); \ + /**/Serial.print(", SDIO->DLEN: "); Serial.print(SDIO->DLEN); \ + Serial.print(", SDIO->DCOUNT: "); Serial.print(SDIO->DCOUNT); \ + Serial.print(", SDIO->STA: "); Serial.println(SDIO->STA, HEX); \ + /*delay(1);*/ \ +} +#define DBG_PIN PD0 + +#else // USE_DEBUG_MODE +#define DBG_PRINT() +#endif // USE_DEBUG_MODE + +/*****************************************************************************/ +static void _panic(const char *message, uint32_t code) +{ + Serial.print(message); Serial.println(code, HEX); + //Block the execution with blinky leds + pinMode(BOARD_LED_PIN, OUTPUT); + pinMode(BOARD_LED2_PIN, OUTPUT); + while (1) { + digitalWrite(BOARD_LED_PIN, HIGH); + digitalWrite(BOARD_LED2_PIN, LOW); + delay(250); + digitalWrite(BOARD_LED_PIN, LOW); + digitalWrite(BOARD_LED2_PIN, HIGH); + delay(250); + } +} +/*===========================================================================*/ +#if USE_YIELD +void yield(void) +{ + uint32_t val = SDIO->STA; + if ( val & SDIO_STA_TRX_ERROR_FLAGS ) { + Serial.print("SDIO ERROR:: SDIO->CLKCR: "); Serial.print(SDIO->CLKCR, HEX); \ + Serial.print(", SDIO->DTIMER: "); Serial.print(SDIO->DTIMER, HEX); \ + Serial.print(", SDIO->DCTRL: "); Serial.print(SDIO->DCTRL, HEX); \ + Serial.print(", SDIO->DLEN: "); Serial.print(SDIO->DLEN); \ + Serial.print(", SDIO->DCOUNT: "); Serial.print(SDIO->DCOUNT); \ + Serial.print(", SDIO->STA: "); Serial.print(SDIO->STA, HEX); \ + Serial.print(", SDIO->RESP0: "); Serial.println(SDIO->RESP[0], HEX); \ + if (val & SDIO_STA_STBITERR) Serial.print(" STBITERR"); + if (val & SDIO_STA_RXOVERR) Serial.print(" RXOVERR"); + if (val & SDIO_STA_TXUNDERR) Serial.print(" TXUNDERR"); + if (val & SDIO_STA_DTIMEOUT) Serial.print(" DTIMEOUT"); + if (val & SDIO_STA_DCRCFAIL) Serial.print(" DCRCFAIL"); + _panic(" - SDIO: Data Transmission Error ", val); + } + + val = dma_get_isr_bit(DMA2, DMA_STREAM3, DMA_ISR_ERROR_BITS); + if ( val & DMA_ISR_FEIF ) { + val ^= DMA_ISR_FEIF; + dma_clear_isr_bit(DMA2, DMA_STREAM3, DMA_ISR_FEIF); + } + if ( val ) { + if (val & DMA_ISR_TEIF) Serial.print(" TEIF"); + if (val & DMA_ISR_DMEIF) Serial.print(" DMEIF"); + //if (val & DMA_ISR_FEIF) Serial.print(" FEIF"); + _panic(" - DMA: Data Transmission Error ", val); + } + //Serial.write('.'); +} +#endif +//============================================================================= +// Error function and macro. +inline bool setSdErrorCode(uint8_t code, uint32_t line) { + m_errorCode = code; + m_errorLine = line; + return false; // setSdErrorCode +} +#define sdError(code) setSdErrorCode(code, __LINE__) +//============================================================================= +/* ISR +void sdhc_isr() { + SDHC_IRQSIGEN = 0; + m_irqstat = SDHC_IRQSTAT; + SDHC_IRQSTAT = m_irqstat; + m_dmaBusy = false; +}*/ +//============================================================================= +// Static functions. +//----------------------------------------------------------------------------- +static bool cardCommand(uint16_t xfertyp, uint32_t arg) +{ +#if USE_DEBUG_MODE==2 + Serial.print("cardCommand: "); Serial.print(xfertyp&SDIO_CMD_CMDINDEX); Serial.print(", arg: "); Serial.print(arg, HEX); +#endif + uint8_t resp = sdio_cmd_send(xfertyp, arg); // returns non-zero if fails, zero if OK +#if USE_DEBUG_MODE==2 + Serial.print(", resp: "); Serial.print(resp, HEX); + Serial.print(", SDIO->STA: "); Serial.print(SDIO->STA, HEX); Serial.print(", cmd_resp: "); Serial.print(SDIO->RESP[0], HEX); + if ( (xfertyp&SDIO_CMD_WAIT_LONG_RESP)==SDIO_CMD_WAIT_LONG_RESP ) { + Serial.print(", "); Serial.print(SDIO->RESP[1], HEX); Serial.print(", "); Serial.print(SDIO->RESP[2], HEX); Serial.print(", "); Serial.println(SDIO->RESP[3], HEX); + } else Serial.println(); +#endif + return resp; // return non-zero when OK +} +//----------------------------------------------------------------------------- +static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) { + return cardCommand(CMD55_XFERTYP, rca) && cardCommand((uint16_t)xfertyp, arg); +} +/*---------------------------------------------------------------------------*/ +static bool cardCMD6(uint32_t arg, uint8_t* status) { + // CMD6 returns 64 bytes. + // use polling only for the moment + if (waitTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + // get the 64 bytes over data lines + sdio_setup_transfer(80000, 64, (SDIO_BLOCKSIZE_64 | SDIO_DIR_RX | SDIO_DCTRL_DTEN)); + + cardCommand(CMD6_XFERTYP, arg); + + // wait data Rx response + if (waitTimeout(isBusyTransferComplete)) { + return sdError(SD_CARD_ERROR_CMD6); + } +DBG_PRINT(); + // copy 64 bytes as 16 words from FIFO to buffer + for (uint8_t i=0; i<16; i++) { + *(uint32_t*)(&status[i<<2]) = SDIO->FIFO; + } + //SDIO->DCTRL = 0; // disable data controller + +#if USE_DEBUG_MODE + Serial.print("read data: "); for (uint8_t i=0; i<17; i++) { Serial.print(status[i], HEX); Serial.print(", "); } Serial.println(); +#endif +return true; +} +//----------------------------------------------------------------------------- +static void initSDHC(void) +{ + sdio_begin(); + DBG_PRINT(); +} +/*---------------------------------------------------------------------------*/ +static bool isBusyCMD13(void) { + if (!cardCommand(CMD13_XFERTYP, m_rca)) { // SEND_STATUS + // Caller will timeout. + return true; + } + return !(SDIO->RESP[0] & CARD_STATUS_READY_FOR_DATA); +} +/*---------------------------------------------------------------------------*/ +static bool isBusyDMA(void) +{ + uint8_t isr = dma_get_isr_bit(DMA2, DMA_STREAM3, (DMA_ISR_TCIF | DMA_ISR_ERROR_BITS)); + //if (isr&DMA_ISR_TCIF) dma_disable(DMA2, DMA_STREAM3); + return !(isr^DMA_ISR_FEIF); // ignore transfer error flag +} +/*---------------------------------------------------------------------------*/ +static bool isBusyTransferComplete(void) +{ + uint32_t mask = SDIO->STA &(SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS); +#if USE_DEBUG_MODE + if ( mask & SDIO_STA_TRX_ERROR_FLAGS ) { + Serial.print("XFER ERROR: SDIO->STA: "); Serial.print(SDIO->STA, HEX); + if (mask & SDIO_STA_STBITERR) Serial.print(" STBITERR"); + if (mask & SDIO_STA_RXOVERR) Serial.print(" RXOVERR"); + if (mask & SDIO_STA_TXUNDERR) Serial.print(" TXUNDERR"); + if (mask & SDIO_STA_DTIMEOUT) Serial.print(" DTIMEOUT"); + if (mask & SDIO_STA_DCRCFAIL) Serial.print(" DCRCFAIL"); + Serial.println(); + } +#endif + if (mask) { + dma_disable(DMA2, DMA_STREAM3); + return false; + } + return true; +} +/*---------------------------------------------------------------------------*/ +static void trxStart(uint8_t* buf, uint32_t n, uint8_t dir) +{ + m_dir = dir; + uint32_t flags = (SDIO_BLOCKSIZE_512 | SDIO_DCTRL_DTEN); + if (dir==TRX_RD) flags |= SDIO_DIR_RX; + // setup SDIO to transfer n blocks of 512 bytes + sdio_setup_transfer(0x00FFFFFF, n, flags); +} +/*---------------------------------------------------------------------------*/ +static bool trxStop() +{ + if (!cardCommand(CMD12_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD12); + } + if ( t ) { + Serial.print(", in "); Serial.println(millis()-t); + t = 0; + } + return true; +} +/*---------------------------------------------------------------------------*/ +static bool dmaTrxStart(uint8_t* buf, uint32_t n, uint8_t dir) +{ + m_dir = dir; + if ((3 & (uint32_t)buf) || n == 0) { // check alignment + _panic("- transferStart: unaligned buffer address ", (uint32_t)buf); + return sdError(SD_CARD_ERROR_DMA); + } + if (dir==TRX_RD && yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } + uint32_t flags = (SDIO_BLOCKSIZE_512 | SDIO_DCTRL_DMAEN | SDIO_DCTRL_DTEN); + if (dir==TRX_RD) flags |= SDIO_DIR_RX; + // setup SDIO to transfer n blocks of 512 bytes + sdio_setup_transfer(0x00FFFFFF, n, flags); + // setup DMA2 stream 3 channel 4 + dma_init(DMA2); + flags = (DMA_PERIF_CTRL | DMA_BURST_INCR4 | DMA_MINC_MODE | DMA_PRIO_VERY_HIGH); + if (dir==TRX_RD) flags |= DMA_FROM_PER; // read + else flags |= DMA_FROM_MEM; // write + dma_setup_transfer(DMA2, DMA_STREAM3, DMA_CH4, DMA_SIZE_32BITS, &SDIO->FIFO, buf, NULL, flags); + dma_set_num_transfers(DMA2, DMA_STREAM3, n); + dma_set_fifo_flags(DMA2, DMA_STREAM3, (DMA_FCR_DMDIS | DMA_FCR_FTH_FULL)); // disable direct mode | threshold FULL + dma_clear_isr_bits(DMA2, DMA_STREAM3); + dma_enable(DMA2, DMA_STREAM3); + return true; +} +/*---------------------------------------------------------------------------*/ +static bool dmaTrxEnd(bool multi_block) +{ + if ( !waitDmaStatus() ) { + DBG_PRINT(); + return sdError(SD_CARD_ERROR_DMA); + } + if ( waitTimeout(isBusyTransferComplete) ) { + if (m_dir==TRX_RD) + return sdError(SD_CARD_ERROR_READ_TIMEOUT); + else + return sdError(SD_CARD_ERROR_WRITE_TIMEOUT); + } + if (multi_block) { + return trxStop(); + } else { + if ( t ) { + Serial.print(", in "); Serial.println(millis()-t); + t = 0; + } + return true; + } +} +//----------------------------------------------------------------------------- +// Read 16 byte CID or CSD register. +static bool readReg16(uint32_t xfertyp, void* data) +{ + uint8_t* d = reinterpret_cast(data); + if (!cardCommand(xfertyp, m_rca)) { + return false; // Caller will set errorCode. + } + *(uint32_t*)(&d[0]) = __builtin_bswap32(SDIO->RESP[0]); + *(uint32_t*)(&d[4]) = __builtin_bswap32(SDIO->RESP[1]); + *(uint32_t*)(&d[8]) = __builtin_bswap32(SDIO->RESP[2]); + *(uint32_t*)(&d[12]) = __builtin_bswap32(SDIO->RESP[3]); + d[15] = 0; + return true; +} +/*---------------------------------------------------------------------------*/ +// Return true if timeout occurs. +static bool yieldTimeout(bool (*fcn)()) { + uint32_t m = millis(); + while (fcn()) { + if ((millis() - m) > BUSY_TIMEOUT_MILLIS) { + return true; + } + yield(); + } + return false; // Caller will set errorCode. +} +/*---------------------------------------------------------------------------*/ +static bool waitDmaStatus(void) +{ + if (yieldTimeout(isBusyDMA)) { + return false; // Caller will set errorCode. + } + return true; +} +/*---------------------------------------------------------------------------*/ +// Return true if timeout occurs. +static bool waitTimeout(bool (*fcn)(void)) { + uint32_t m = millis(); + while (fcn()) { + if ((millis() - m) > BUSY_TIMEOUT_MILLIS) { + return true; + } + delayMicroseconds(1); + } + return false; // Caller will set errorCode. +} + +uint32_t aligned[128]; // temporary buffer for misaligned buffers +//============================================================================= +bool SdioCard::begin(void) +{ + m_initDone = false; + m_errorCode = SD_CARD_ERROR_NONE; + m_highCapacity = false; + m_version2 = false; + +#if USE_DEBUG_MODE +pinMode(DBG_PIN, OUTPUT); +digitalWrite(DBG_PIN, HIGH); +delay(100); +#endif + // initialize controller. + initSDHC(); + + if (!cardCommand(CMD0_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD0); + } + // Try several times for case of reset delay. + for (uint32_t i = 0; i < CMD8_RETRIES; i++) { + if (cardCommand(CMD8_XFERTYP, 0X1AA)) { + if (SDIO->RESP[0] != 0X1AA) { + return sdError(SD_CARD_ERROR_CMD8); + } + m_version2 = true; + break; + } + } + uint32_t arg = m_version2 ? 0X40300000 : 0x00300000; + uint32_t m = millis(); + do { + if (!cardAcmd(0, ACMD41_XFERTYP, arg) || + ((millis() - m) > BUSY_TIMEOUT_MILLIS)) { + return sdError(SD_CARD_ERROR_ACMD41); + } + } while ((SDIO->RESP[0] & 0x80000000) == 0); + + m_ocr = SDIO->RESP[0]; + if (m_ocr & 0x40000000) { + // Is high capacity. + m_highCapacity = true; + } + if (!cardCommand(CMD2_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD2); + } + if (!cardCommand(CMD3_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD3); + } + m_rca = SDIO->RESP[0] & 0xFFFF0000; + if (!readReg16(CMD9_XFERTYP, &m_csd)) { + return sdError(SD_CARD_ERROR_CMD9); + } + if (!readReg16(CMD10_XFERTYP, &m_cid)) { + return sdError(SD_CARD_ERROR_CMD10); + } + if (!cardCommand(CMD7_XFERTYP, m_rca)) { + return sdError(SD_CARD_ERROR_CMD7); + } + // Set card to bus width four. + if (!cardAcmd(m_rca, ACMD6_XFERTYP, 2)) { + return sdError(SD_CARD_ERROR_ACMD6); + } + sdio_set_dbus_width(SDIO_CLKCR_WIDBUS_4BIT); + + // Determine if High Speed mode is supported and set frequency. + uint8_t status[64]; + // see "Physical Layer Simplified Specification Version 6.00", chapter 4.3.10, Table 4-13. + // Support Bits of Functions in Function Group 1: bits 415:400, which are bytes [12][13] + // Function Selection of Function Group 1: bits 379:376, which is low nibble of byte [16] + if (cardCMD6(0X00FFFFFF, status) && (2 & status[13]) && + cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) { + //Serial.println("\n*** 50MHz clock supported ***"); + } else { + _panic("*** Only 25MHz clock supported! ***", 0); + } + + m_sdClkKhz = 24000; + sdio_set_clock(m_sdClkKhz*1000); // set clock to 24MHz + + m_initDone = true; + return true; +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::cardSize(void) { + return sdCardCapacity(&m_csd); +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::erase(uint32_t firstBlock, uint32_t lastBlock) { + // check for single block erase + if (!m_csd.v1.erase_blk_en) { + // erase size mask + uint8_t m = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low; + if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { + // error card can't erase specified area + return sdError(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + } + } + if (!m_highCapacity) { + firstBlock <<= 9; + lastBlock <<= 9; + } + if (!cardCommand(CMD32_XFERTYP, firstBlock)) { + return sdError(SD_CARD_ERROR_CMD32); + } + if (!cardCommand(CMD33_XFERTYP, lastBlock)) { + return sdError(SD_CARD_ERROR_CMD33); + } + if (!cardCommand(CMD38_XFERTYP, 0)) { + return sdError(SD_CARD_ERROR_CMD38); + } + if (waitTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_ERASE_TIMEOUT); + } + return true; +} +//----------------------------------------------------------------------------- +uint8_t SdioCard::errorCode() { + return m_errorCode; +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::errorData() { + return m_irqstat; +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::errorLine() { + return m_errorLine; +} +//----------------------------------------------------------------------------- +bool SdioCard::isBusy() { + return m_busyFcn ? m_busyFcn() : m_initDone && isBusyCMD13(); +} +//----------------------------------------------------------------------------- +uint32_t SdioCard::kHzSdClk() { + return m_sdClkKhz; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readBlock(uint32_t lba, uint8_t* buf) +{ +#if USE_DEBUG_MODE + Serial.print("readBlock: "); Serial.println(lba); //Serial.print(", buf: "); Serial.println((uint32_t)buf, HEX); +#endif + // prepare SDIO and DMA for data read transfer + dmaTrxStart((uint32_t)buf & 3 ? (uint8_t*)aligned : buf, 512, TRX_RD); + // send command to start data transfer + if ( !cardCommand(CMD17_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD17); + } + if ( dmaTrxEnd(0)) { + if ( (uint32_t)buf & 3 ) { + //memcpy(buf, aligned, 512); + register uint8_t * dst = buf; + register uint8_t * src = (uint8_t *)aligned; + register uint16_t i = 64; + while ( i-- ) { // do 8 byte copies, is much faster than single byte copy + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + } + } + return true; + } + return false; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readBlocks(uint32_t lba, uint8_t* buf, size_t n) +{ +#if USE_DEBUG_MODE + Serial.print("readBlocks: "); Serial.print(lba); + //Serial.print(", buf: "); Serial.print((uint32_t)buf, HEX); + Serial.print(", "); Serial.println(n); +#endif + if ((uint32_t)buf & 3) { + for (size_t i = 0; i < n; i++, lba++, buf += 512) { + if (!readBlock(lba, buf)) { + return false; // readBlock will set errorCode. + } + } + return true; + } + // prepare SDIO and DMA for data read transfer + dmaTrxStart(buf, 512*n, TRX_RD); + // send command to start data transfer + if ( !cardCommand(CMD18_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD18); + } + return dmaTrxEnd(1); +} +//----------------------------------------------------------------------------- +bool SdioCard::readCID(void* cid) { + memcpy(cid, &m_cid, 16); + return true; +} +//----------------------------------------------------------------------------- +bool SdioCard::readCSD(void* csd) { + memcpy(csd, &m_csd, 16); + return true; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readData(uint8_t *dst) +{ + //Serial.print("readData: "); Serial.print(m_lba); Serial.print(", m_cnt: "); Serial.println(m_cnt); + if ( m_cnt==0 ) return false; + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // non-DMA block read + trxStart(dst, 512, TRX_RD); + // send command to start data transfer + if ( !cardCommand(CMD17_XFERTYP, (m_highCapacity ? m_lba : 512*m_lba)) ) { + return sdError(SD_CARD_ERROR_CMD17); + } + // Receive a data block from the SDIO + register uint32_t STA; // to speed up SDIO flags checking + register uint16_t cnt = 512; + register uint32_t * ptr = (uint32_t *)dst; + // ----> TIME CRITICAL SECTION BEGIN <---- + do { + STA = SDIO->STA; + if (STA & SDIO_STA_RXFIFOHF) { + // Receive FIFO half full, there are at least 8 words in it + noInterrupts(); + *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; + *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; *ptr++ = SDIO->FIFO; + interrupts(); + cnt -= 8; + } + } while ( !(STA & (SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) ); + // <---- TIME CRITICAL SECTION END ----> + + // read data still available in FIFO + while ( (SDIO->STA & SDIO_STA_RXDAVL) && (cnt--) ) { + *ptr++ = SDIO->FIFO; + } + // check error, temporary stuff, remove for final version + if ( SDIO->STA & SDIO_STA_TRX_ERROR_FLAGS ) { + _panic("ERROR: non-DMA read error ", SDIO->STA); + return false; + } + m_lba++; + m_cnt--; + return !(SDIO->STA&SDIO_STA_TRX_ERROR_FLAGS); +} +//----------------------------------------------------------------------------- +bool SdioCard::readOCR(uint32_t* ocr) { + *ocr = m_ocr; + return true; +} +//----------------------------------------------------------------------------- +bool SdioCard::readStart(uint32_t lba) +{ + m_lba = lba; + m_cnt = 1024; + return true; +} +/*---------------------------------------------------------------------------*/ +// SDHC will do Auto CMD12 after count blocks. +bool SdioCard::readStart(uint32_t lba, uint32_t count) +{ + //Serial.print("readStart: "); Serial.print(lba); Serial.print(", cnt: "); Serial.println(count); + m_lba = lba; + m_cnt = count; + return true; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::readStop() +{ + //Serial.println("readStop."); + m_lba = 0; + m_cnt = 0; + return true; +} +//----------------------------------------------------------------------------- +bool SdioCard::syncBlocks() { + return true; +} +//----------------------------------------------------------------------------- +uint8_t SdioCard::type() { + return m_version2 ? m_highCapacity ? + SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeBlock(uint32_t lba, const uint8_t* buf) +{ +#if USE_DEBUG_MODE + Serial.print("writeBlock: "); Serial.println(lba); //Serial.print(", buf: "); Serial.println((uint32_t)buf, HEX); +#endif + uint8_t * ptr = (uint8_t *)buf; + if (3 & (uint32_t)ptr) { + Serial.print("writeBlock: "); Serial.print(lba); + Serial.print(", buf: "); Serial.print((uint32_t)ptr, HEX); + //memcpy(aligned, buf, 512); + register uint8_t * src = (uint8_t *)ptr; + ptr = (uint8_t *)aligned; + register uint8_t * dst = ptr; + register uint16_t i = 64; + while ( i-- ) { // do 8 byte copies, is much faster than single byte copy + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; + } + } + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // send command to start data transfer + if ( !cardCommand(CMD24_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD24); + } + // prepare SDIO and DMA for data transfer + dmaTrxStart(ptr, 512, TRX_WR); // 1 block, write transfer + + return dmaTrxEnd(0); +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeBlocks(uint32_t lba, const uint8_t* buf, size_t n) +{ +#if USE_DEBUG_MODE + Serial.print("writeBlocks: "); Serial.print(lba); + //Serial.print(", buf: "); Serial.print((uint32_t)buf, HEX); + Serial.print(", "); Serial.println(n); +#endif + if (3 & (uint32_t)buf) { // misaligned buffer address, write single blocks + for (size_t i = 0; i < n; i++, lba++, buf += 512) { + if (!writeBlock(lba, buf)) { + return false; // writeBlock will set errorCode. + } + } + return true; + } + if (yieldTimeout(isBusyCMD13)) { + return sdError(SD_CARD_ERROR_CMD13); + } +#if 0 + // set number of blocks to write - this can speed up block write + if ( !cardAcmd(m_rca, ACMD23_XFERTYP, n) ) { + return sdError(SD_CARD_ERROR_ACMD23); + } +#endif + // send command to start data transfer + if ( !cardCommand(CMD25_XFERTYP, (m_highCapacity ? lba : 512*lba)) ) { + return sdError(SD_CARD_ERROR_CMD25); + } + // prepare SDIO and DMA for data transfer + dmaTrxStart((uint8_t *)buf, 512*n, TRX_WR); // n blocks, write transfer + + return dmaTrxEnd(1); +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeData(const uint8_t* src) +{ + //Serial.print("writeData: "); Serial.print(m_lba); Serial.print(", cnt: "); Serial.println(m_cnt); + if ( !m_cnt ) return false; + if (yieldTimeout(isBusyCMD13)) { // wait for previous transmission end + return sdError(SD_CARD_ERROR_CMD13); + } + // send command to start block data transfer + if ( !cardCommand(CMD24_XFERTYP, (m_highCapacity ? m_lba : 512*m_lba)) ) { + return sdError(SD_CARD_ERROR_CMD24); + } + // non-DMA block write + trxStart((uint8_t*)src, 512, TRX_WR); + // Receive a data block from the SDIO + register uint32_t STA; // to speed up SDIO flags checking + register uint16_t cnt = 512; + register uint32_t * ptr = (uint32_t*)src; + // pre-fill up the FIFO with 32 words + noInterrupts(); + while ( (cnt--)>(512-32) ) SDIO->FIFO = *ptr++; + interrupts(); + // ----> TIME CRITICAL SECTION BEGIN <---- + do { + STA = SDIO->STA; + if (STA & SDIO_STA_TXFIFOHE) { + // Transmit FIFO half empty, fill up the remaining 16 words + noInterrupts(); + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; SDIO->FIFO = *ptr++; + interrupts(); + cnt -= 16; + } + } while ( !(STA & (SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) && cnt); + // <---- TIME CRITICAL SECTION END ----> + if ( waitTimeout(isBusyTransferComplete) ) { + return sdError(SD_CARD_ERROR_WRITE_TIMEOUT); + } + m_lba++; + m_cnt--; + if (SDIO->STA&SDIO_STA_TRX_ERROR_FLAGS) { + _panic("writeData error: ", SDIO->STA); + } + return !(SDIO->STA&SDIO_STA_TRX_ERROR_FLAGS); +} +//----------------------------------------------------------------------------- +bool SdioCard::writeStart(uint32_t lba) +{ + m_lba = lba; + m_cnt = 1024; + return true; +} +/*---------------------------------------------------------------------------*/ +// SDHC will do Auto CMD12 after count blocks. +bool SdioCard::writeStart(uint32_t lba, uint32_t count) +{ + //Serial.print("writeStart: "); Serial.print(lba); Serial.print(", cnt: "); Serial.println(count); + m_lba = lba; + m_cnt = count; + return true; +} +/*---------------------------------------------------------------------------*/ +bool SdioCard::writeStop() +{ + //Serial.println("writeStop."); + m_lba = 0; + m_cnt = 0; + return true; +} diff --git a/STM32F4/libraries/SDIO/SdioF4.h b/STM32F4/libraries/SDIO/SdioF4.h new file mode 100644 index 0000000..c995b1c --- /dev/null +++ b/STM32F4/libraries/SDIO/SdioF4.h @@ -0,0 +1,7 @@ + +#ifndef _SDIOF4_H_ +#define _SDIOF4_H_ + +#include + +#endif diff --git a/STM32F4/libraries/SPI/library.properties b/STM32F4/libraries/SPI/library.properties index 6f20f01..ba3a577 100644 --- a/STM32F4/libraries/SPI/library.properties +++ b/STM32F4/libraries/SPI/library.properties @@ -7,3 +7,4 @@ paragraph=SPI for STM32F4 category=Communication url= architectures=STM32F4 +maintainer= \ No newline at end of file diff --git a/STM32F4/libraries/SPI/src/SPI.cpp b/STM32F4/libraries/SPI/src/SPI.cpp index 08fbbd5..72a4c48 100644 --- a/STM32F4/libraries/SPI/src/SPI.cpp +++ b/STM32F4/libraries/SPI/src/SPI.cpp @@ -40,9 +40,9 @@ #include "wirish.h" #include "boards.h" -//#include "HardwareSerial.h" +#define DMA_TIMEOUT 100 -#if CYCLES_PER_MICROSECOND != 72 +#if CYCLES_PER_MICROSECOND != 168 /* TODO [0.2.0?] something smarter than this */ #warning "Unexpected clock speed; SPI frequency calculation will be incorrect" #endif @@ -91,77 +91,115 @@ static const spi_pins board_spi_pins[] __FLASH__ = { */ SPIClass::SPIClass(uint32 spi_num) { + + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed + + switch (spi_num) { #if BOARD_NR_SPI >= 1 case 1: - this->spi_d = SPI1; + _currentSetting->spi_d = SPI1; break; #endif #if BOARD_NR_SPI >= 2 case 2: - this->spi_d = SPI2; + _currentSetting->spi_d = SPI2; break; #endif #if BOARD_NR_SPI >= 3 case 3: - this->spi_d = SPI3; + _currentSetting->spi_d = SPI3; break; #endif default: ASSERT(0); } - //pinMode(BOARD_SPI_DEFAULT_SS,OUTPUT); - - clockDivider = SPI_BAUD_PCLK_DIV_16; - dataMode = SPI_MODE0; + // Init things specific to each SPI device + // clock divider setup is a bit of hack, and needs to be improved at a later date. +/*****************************************************************************/ +// DMA / Channel / Stream +// Rx Tx +// SPI1: 2 / 3 / 0 (2) - 2 / 3 / 3 (5) +// SPI2: 1 / 0 / 3 - 1 / 0 / 4 +// SPI3: 1 / 0 / 0 (2) - 1 / 0 / 5 (7) +/*****************************************************************************/ + _settings[0].spi_d = SPI1; + _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); +#ifdef SPI_DMA + _settings[0].spiDmaDev = DMA2; + _settings[0].spiDmaChannel = DMA_CH3; + _settings[0].spiRxDmaStream = DMA_STREAM0; // alternative: DMA_STREAM2 + _settings[0].spiTxDmaStream = DMA_STREAM3; // alternative: DMA_STREAM5 +#endif + _settings[1].spi_d = SPI2; + _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); +#ifdef SPI_DMA + _settings[1].spiDmaDev = DMA1; + _settings[1].spiDmaChannel = DMA_CH0; + _settings[1].spiRxDmaStream = DMA_STREAM3; // alternative: - + _settings[1].spiTxDmaStream = DMA_STREAM4; // alternative: - +#endif +#if BOARD_NR_SPI >= 3 + _settings[2].spi_d = SPI3; + _settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock); +#ifdef SPI_DMA + _settings[2].spiDmaDev = DMA1; + _settings[2].spiDmaChannel = DMA_CH0; + _settings[2].spiRxDmaStream = DMA_STREAM0; // alternative: DMA_STREAM2 + _settings[2].spiTxDmaStream = DMA_STREAM5; // alternative: DMA_STREAM7 +#endif +#endif + } /* * Set up/tear down */ +void SPIClass::updateSettings(void) { + uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE | SPI_SOFT_SS); + #ifdef SPI_DEBUG + Serial.print("spi_master_enable("); Serial.print(_currentSetting->clockDivider); Serial.print(","); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")"); + #endif + spi_master_enable(_currentSetting->spi_d, (spi_baud_rate)_currentSetting->clockDivider, (spi_mode)_currentSetting->dataMode, flags); +} void SPIClass::begin(void) { - - uint32 flags = ((bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | SPI_DFF_8_BIT | SPI_SW_SLAVE | SPI_SOFT_SS); - spi_init(spi_d); - configure_gpios(spi_d, 1); - #ifdef SPI_DEBUG - Serial.print("spi_master_enable("); Serial.print(clockDivider); Serial.print(","); Serial.print(dataMode); Serial.print(","); Serial.print(flags); Serial.println(")"); - #endif - spi_master_enable(spi_d, (spi_baud_rate)clockDivider, (spi_mode)dataMode, flags); + spi_init(_currentSetting->spi_d); + configure_gpios(_currentSetting->spi_d, 1); + updateSettings(); +#ifdef SPI_USE_DMA_BUFFER + dmaSendBufferInit(); +#endif +//Serial.println("SPI class begin - end"); } void SPIClass::beginSlave(void) { - if (dataMode >= 4) { - ASSERT(0); - return; - } - uint32 flags = ((bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | SPI_DFF_8_BIT | SPI_SW_SLAVE); - spi_init(spi_d); - configure_gpios(spi_d, 0); + spi_init(_currentSetting->spi_d); + configure_gpios(_currentSetting->spi_d, 0); + uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_RX_ONLY); #ifdef SPI_DEBUG - Serial.print("spi_slave_enable("); Serial.print(dataMode); Serial.print(","); Serial.print(flags); Serial.println(")"); + Serial.print("spi_slave_enable("); Serial.print(_currentSetting->dataMode); Serial.print(","); Serial.print(flags); Serial.println(")"); #endif - spi_slave_enable(spi_d, (spi_mode)dataMode, flags); + spi_slave_enable(_currentSetting->spi_d, (spi_mode)_currentSetting->dataMode, flags); } void SPIClass::end(void) { - if (!spi_is_enabled(this->spi_d)) { + if (!spi_is_enabled(_currentSetting->spi_d)) { return; } // Follows RM0008's sequence for disabling a SPI in master/slave // full duplex mode. - while (spi_is_rx_nonempty(this->spi_d)) { + while (spi_is_rx_nonempty(_currentSetting->spi_d)) { // FIXME [0.1.0] remove this once you have an interrupt based driver - volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); + volatile uint16 rx __attribute__((unused)) = spi_rx_reg(_currentSetting->spi_d); } - while (!spi_is_tx_empty(this->spi_d)) + while (!spi_is_tx_empty(_currentSetting->spi_d)) ; - while (spi_is_busy(this->spi_d)) + while (spi_is_busy(_currentSetting->spi_d)) ; - spi_peripheral_disable(this->spi_d); + spi_peripheral_disable(_currentSetting->spi_d); } /* Roger Clark added 3 functions */ @@ -170,8 +208,9 @@ void SPIClass::setClockDivider(uint32_t clockDivider) #ifdef SPI_DEBUG Serial.print("Clock divider set to "); Serial.println(clockDivider); #endif - this->clockDivider = clockDivider; - this->begin(); + _currentSetting->clockDivider = clockDivider; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_BR); + _currentSetting->spi_d->regs->CR1 = cr1 | (clockDivider & SPI_CR1_BR); } void SPIClass::setBitOrder(BitOrder bitOrder) @@ -179,8 +218,10 @@ void SPIClass::setBitOrder(BitOrder bitOrder) #ifdef SPI_DEBUG Serial.print("Bit order set to "); Serial.println(bitOrder); #endif - this->bitOrder = bitOrder; - this->begin(); + _currentSetting->bitOrder = bitOrder; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_LSBFIRST); + if ( bitOrder==LSBFIRST ) cr1 |= SPI_CR1_LSBFIRST; + _currentSetting->spi_d->regs->CR1 = cr1; } /* Victor Perez. Added to test changing datasize from 8 to 16 bit modes on the fly. @@ -189,11 +230,11 @@ void SPIClass::setBitOrder(BitOrder bitOrder) */ void SPIClass::setDataSize(uint32 datasize) { - uint32 cr1 = this->spi_d->regs->CR1; - datasize &= SPI_CR1_DFF; - cr1 &= ~(SPI_CR1_DFF); - cr1 |= datasize; - this->spi_d->regs->CR1 = cr1; + _currentSetting->dataSize = datasize; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF); + uint8 en = spi_is_enabled(_currentSetting->spi_d); + spi_peripheral_disable(_currentSetting->spi_d); + _currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF) | en; } void SPIClass::setDataMode(uint8_t dataMode) @@ -212,13 +253,11 @@ SPI Mode CPOL CPHA Shift SCK-edge Capture SCK-edge On the STM32 it appears to be bit 1 - CPOL : Clock polarity - (This bit should not be changed when communication is ongoing) 0 : CLK to 0 when idle 1 : CLK to 1 when idle bit 0 - CPHA : Clock phase - (This bit should not be changed when communication is ongoing) 0 : The first clock transition is the first data capture edge 1 : The second clock transition is the first data capture edge @@ -228,44 +267,32 @@ If someone finds this is not the case or sees a logic error with this let me kno #ifdef SPI_DEBUG Serial.print("Data mode set to "); Serial.println(dataMode); #endif - this->dataMode = dataMode; - this->begin(); -} - + _currentSetting->dataMode = dataMode; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_CPOL|SPI_CR1_CPHA); + _currentSetting->spi_d->regs->CR1 = cr1 | (dataMode & (SPI_CR1_CPOL|SPI_CR1_CPHA)); +} void SPIClass::beginTransaction(uint8_t pin, SPISettings settings) { #ifdef SPI_DEBUG Serial.println("SPIClass::beginTransaction"); #endif - //_SSPin=pin; - //pinMode(_SSPin,OUTPUT); - //digitalWrite(_SSPin,LOW); setBitOrder(settings.bitOrder); setDataMode(settings.dataMode); - setClockDivider(determine_baud_rate(spi_d, settings.clock)); + setDataSize(settings.dataSize); + setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock)); begin(); -#if 0 -// code from SAM core - uint8_t mode = interruptMode; - if (mode > 0) { - if (mode < 16) { - if (mode & 1) PIOA->PIO_IDR = interruptMask[0]; - if (mode & 2) PIOB->PIO_IDR = interruptMask[1]; - if (mode & 4) PIOC->PIO_IDR = interruptMask[2]; - if (mode & 8) PIOD->PIO_IDR = interruptMask[3]; - } else { - interruptSave = interruptsStatus(); - noInterrupts(); - } - } - uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(pin); - bitOrder[ch] = settings.border; - SPI_ConfigureNPCS(spi, ch, settings.config); - //setBitOrder(pin, settings.border); - //setDataMode(pin, settings.datamode); - //setClockDivider(pin, settings.clockdiv); -#endif +} + +void SPIClass::beginTransactionSlave(SPISettings settings) +{ + #ifdef SPI_DEBUG + Serial.println(F("SPIClass::beginTransactionSlave")); + #endif + setBitOrder(settings.bitOrder); + setDataMode(settings.dataMode); + setDataSize(settings.dataSize); + beginSlave(); } void SPIClass::endTransaction(void) @@ -295,131 +322,152 @@ void SPIClass::endTransaction(void) * I/O */ -uint8 SPIClass::read(void) { - uint8 buf[1]; - this->read(buf, 1); - return buf[0]; +uint16 SPIClass::read(void) +{ + while ( spi_is_rx_nonempty(_currentSetting->spi_d)==0 ) ; + return (uint16)spi_rx_reg(_currentSetting->spi_d); } -void SPIClass::read(uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (rxed < len) { - while (!spi_is_rx_nonempty(this->spi_d)) - ; - buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); - } +void SPIClass::read(uint8 *buf, uint32 len) +{ + if ( len == 0 ) return; + spi_rx_reg(_currentSetting->spi_d); // clear the RX buffer in case a byte is waiting on it. + spi_reg_map * regs = _currentSetting->spi_d->regs; + // start sequence: write byte 0 + regs->DR = 0x00FF; // write the first byte + // main loop + while ( (--len) ) { + while( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag + noInterrupts(); // go atomic level - avoid interrupts to surely get the previously received data + regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag. + while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register + *buf++ = (uint8)(regs->DR); // read and store the received byte. This clears the RXNE flag. + interrupts(); // let systick do its job + } + // read remaining last byte + while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the Rx register + *buf++ = (uint8)(regs->DR); // read and store the received byte } -void SPIClass::write(uint16 data) { - #ifdef SPI_DEBUG -// Serial.print("SPIClass::write("); Serial.print(data); Serial.println(")"); - #endif - // this->write(&data, 1); - +void SPIClass::write(uint16 data) +{ /* Added for 16bit data Victor Perez. Roger Clark - * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte) - * The original method, of calling write(*data, length) . + * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, + * by taking the Tx code from transfer(byte) * This almost doubles the speed of this function. */ - - spi_tx_reg(this->spi_d, data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." - while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_reg(_currentSetting->spi_d, data); // write the data to be transmitted into the SPI_DR register (this clears the TXE flag) + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." } -//void SPIClass::write(uint8 byte) { - // this->write(&byte, 1); - - /* Roger Clark - * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte) - * The original method, of calling write(*data, length) . - * This almost doubles the speed of this function. - */ - -// spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." -// while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." -// while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." -//} - -void SPIClass::write(const uint8 *data, uint32 length) { - #ifdef SPI_DEBUG - Serial.print("SPIClass::write(data, "); Serial.print(length); Serial.println(")"); - #endif - uint32 txed = 0; - while (txed < length) { - txed += spi_tx(this->spi_d, data + txed, length - txed); - } - while (spi_is_tx_empty(this->spi_d) == 0); // "4. After writing the last data item into the SPI_DR register, wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... then wait until BSY=0, this indicates that the transmission of the last data is complete." +void SPIClass::write(uint16 data, uint32 n) +{ + // Added by stevstrong: Repeatedly send same data by the specified number of times + spi_reg_map * regs = _currentSetting->spi_d->regs; + while ( (n--)>0 ) { + regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag) + while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty + } + while ( (regs->SR & SPI_SR_BSY) != 0); // wait until BSY=0 before returning } -uint8 SPIClass::transfer(uint8 byte) const { - #ifdef SPI_DEBUG -// Serial.print("SPIClass::transfer("); Serial.print(byte); Serial.println(")"); - #endif - uint8 b; - spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." - while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..." - b = spi_rx_reg(this->spi_d); // "... and read the last received data." - while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - return b; +void SPIClass::write(const void *data, uint32 length) +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_tx(spi_d, (void*)data, length); // data can be array of bytes or words + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." } + +uint8 SPIClass::transfer(uint8 byte) const +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_rx_reg(spi_d); // read any previous data + spi_tx_reg(spi_d, byte); // Write the data item to be transmitted into the SPI_DR register + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + return (uint8)spi_rx_reg(spi_d); // "... and read the last received data." +} + +uint16_t SPIClass::transfer16(uint16_t wr_data) const +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_rx_reg(spi_d); // read any previous data + spi_tx_reg(spi_d, wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + return (uint16)spi_rx_reg(spi_d); // "... and read the last received data." +} + +#ifdef SPI_DMA /* Roger Clark and Victor Perez, 2015 * Performs a DMA SPI transfer with at least a receive buffer. -* If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer. -* On exit TX buffer is not modified, and RX buffer cotains the received data. +* If a TX buffer is not provided, FF is sent over and over for the length of the transfer. +* On exit TX buffer is not modified, and RX buffer contains the received data. * Still in progress. */ -uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length) { +uint8 SPIClass::dmaTransfer(const void * transmitBuf, void * receiveBuf, uint16 length) +{ if (length == 0) return 0; - uint8 b; - if (spi_is_rx_nonempty(this->spi_d) == 1) b = spi_rx_reg(this->spi_d); //Clear the RX buffer in case a byte is waiting on it. - dma1_ch3_Active=true; - dma_init(DMA1); - dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); - - // RX - spi_rx_dma_enable(SPI1); - dma_setup_transfer(DMA1, DMA_CH2, &SPI1->regs->DR, DMA_SIZE_8BITS, - receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA - dma_set_num_transfers(DMA1, DMA_CH2, length); - - // TX - spi_tx_dma_enable(SPI1); - if (!transmitBuf) { - static uint8_t ff = 0XFF; - transmitBuf = &ff; - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, - transmitBuf, DMA_SIZE_8BITS, (DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit FF repeatedly - } - else { - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, - transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit buffer DMA - } - dma_set_num_transfers(DMA1, DMA_CH3, length); - dma_enable(DMA1, DMA_CH2);// enable receive - dma_enable(DMA1, DMA_CH3);// enable transmit + uint8 b = 0; + + dma_init(_currentSetting->spiDmaDev); +// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); + // RX + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==SPI_DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer( _currentSetting->spiDmaDev, + _currentSetting->spiRxDmaStream, + _currentSetting->spiDmaChannel, + dma_bit_size, + &_currentSetting->spi_d->regs->DR, // peripheral address + receiveBuf, // memory bank 0 address + NULL, // memory bank 1 address + (DMA_MINC_MODE | DMA_FROM_PER | DMA_PRIO_VERY_HIGH) // flags + ); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream, length); + dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream, 0); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream); + + // TX + uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM); // | DMA_TRNS_CMPLT); + if ( transmitBuf==0 ) { + static uint8_t ff = 0XFF; + transmitBuf = &ff; + flags &= ~((uint32)DMA_MINC_MODE); // remove increment mode + } + dma_setup_transfer( _currentSetting->spiDmaDev, + _currentSetting->spiTxDmaStream, + _currentSetting->spiDmaChannel, + dma_bit_size, + &_currentSetting->spi_d->regs->DR, // peripheral address + (volatile void*)transmitBuf, // memory bank 0 address + NULL, // memory bank 1 address + flags + ); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, length); + dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, 0); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream); + // software enable sequence, see AN4031, chapter 4.3 + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream);// enable receive + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);// enable transmit + spi_rx_reg(_currentSetting->spi_d); //Clear the RX buffer in case a byte is waiting on it. + spi_rx_dma_enable(_currentSetting->spi_d); + spi_tx_dma_enable(_currentSetting->spi_d); // must be the last enable to avoid DMA error flag -// while (dma1_ch3_Active); -// if (receiveBuf) { uint32_t m = millis(); - while (dma1_ch3_Active) { - if ((millis() - m) > 100) { - dma1_ch3_Active = 0; - b = 2; - break; - } + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream) & DMA_ISR_TCIF)==0 ) {// wait for completion flag to be set + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } } -// } - while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(DMA1, DMA_CH3); - dma_disable(DMA1, DMA_CH2); - spi_rx_dma_disable(SPI1); - spi_tx_dma_disable(SPI1); + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + // software disable sequence, see AN4031, chapter 4.1 + spi_tx_dma_disable(_currentSetting->spi_d); + spi_rx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaStream); return b; } @@ -427,56 +475,43 @@ uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length * Performs a DMA SPI send using a TX buffer. * On exit TX buffer is not modified. * Still in progress. +* 2016 - stevstrong - reworked to automatically detect bit size from SPI setting */ -uint8 SPIClass::dmaSend(uint8 *transmitBuf, uint16 length, bool minc) { +uint8 SPIClass::dmaSend(const void * transmitBuf, uint16 length, bool minc) +{ if (length == 0) return 0; - uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); - uint8 b; - dma1_ch3_Active=true; - dma_init(DMA1); - dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); - + uint8 b = 0; + dma_init(_currentSetting->spiDmaDev); // TX - spi_tx_dma_enable(SPI1); - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, - transmitBuf, DMA_SIZE_8BITS, flags);// Transmit buffer DMA - dma_set_num_transfers(DMA1, DMA_CH3, length); - dma_enable(DMA1, DMA_CH3);// enable transmit - - while (dma1_ch3_Active); - while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..." - b = spi_rx_reg(this->spi_d); // "... and read the last received data." - while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(DMA1, DMA_CH3); - spi_tx_dma_disable(SPI1); - return b; -} + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==SPI_DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer( _currentSetting->spiDmaDev, + _currentSetting->spiTxDmaStream, + _currentSetting->spiDmaChannel, + dma_bit_size, + &_currentSetting->spi_d->regs->DR, // peripheral address + (volatile void*)transmitBuf, // memory bank 0 address + NULL, // memory bank 1 address + ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM ) //| DMA_TRNS_CMPLT ) // flags + );// Transmit buffer DMA + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, length); + dma_set_fifo_flags(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream, 0); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream);// enable transmit + spi_tx_dma_enable(_currentSetting->spi_d); -uint8 SPIClass::dmaSend(uint16 *transmitBuf, uint16 length, bool minc) { - if (length == 0) return 0; - uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); - uint8 b; - dma1_ch3_Active=true; - dma_init(DMA1); - dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); + uint32_t m = millis(); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream) & DMA_ISR_TCIF)==0 ) {// wait for completion flag to be set + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } - // TX - spi_tx_dma_enable(SPI1); - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_16BITS, - transmitBuf, DMA_SIZE_16BITS, flags);// Transmit buffer DMA - dma_set_num_transfers(DMA1, DMA_CH3, length); - dma_enable(DMA1, DMA_CH3);// enable transmit - - while (dma1_ch3_Active); - while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..." - b = spi_rx_reg(this->spi_d); // "... and read the last received data." - while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(DMA1, DMA_CH3); - spi_tx_dma_disable(SPI1); - return b; + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaStream); + return b; } +#endif + void SPIClass::attachInterrupt(void) { @@ -492,19 +527,19 @@ void SPIClass::detachInterrupt(void) { */ uint8 SPIClass::misoPin(void) { - return dev_to_spi_pins(this->spi_d)->miso; + return dev_to_spi_pins(_currentSetting->spi_d)->miso; } uint8 SPIClass::mosiPin(void) { - return dev_to_spi_pins(this->spi_d)->mosi; + return dev_to_spi_pins(_currentSetting->spi_d)->mosi; } uint8 SPIClass::sckPin(void) { - return dev_to_spi_pins(this->spi_d)->sck; + return dev_to_spi_pins(_currentSetting->spi_d)->sck; } uint8 SPIClass::nssPin(void) { - return dev_to_spi_pins(this->spi_d)->nss; + return dev_to_spi_pins(_currentSetting->spi_d)->nss; } /* @@ -512,18 +547,13 @@ uint8 SPIClass::nssPin(void) { */ uint8 SPIClass::send(uint8 data) { - uint8 buf[] = {data}; - return this->send(buf, 1); + this->write(data); + return 1; } uint8 SPIClass::send(uint8 *buf, uint32 len) { - uint32 txed = 0; - uint8 ret = 0; - while (txed < len) { - this->write(buf[txed++]); - ret = this->read(); - } - return ret; + this->write(buf, len); + return len; } uint8 SPIClass::recv(void) { @@ -581,33 +611,7 @@ static void configure_gpios(spi_dev *dev, bool as_master) { Serial.println(")"); #endif -#ifdef STM32F4 - if(dev->clk_id <= RCC_SPI2) { - if(nssi) { - if(!as_master) { - gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 5); - } - } - gpio_set_af_mode(scki->gpio_device, scki->gpio_bit, 5); - gpio_set_af_mode(misoi->gpio_device, misoi->gpio_bit, 5); - gpio_set_af_mode(mosii->gpio_device, mosii->gpio_bit, 5); - } else { - if(nssi) { - if(!as_master) { - gpio_set_af_mode(nssi->gpio_device, scki->gpio_bit, 6); - } - } - gpio_set_af_mode(scki->gpio_device, scki->gpio_bit, 6); - gpio_set_af_mode(misoi->gpio_device, misoi->gpio_bit, 6); - gpio_set_af_mode(mosii->gpio_device, mosii->gpio_bit, 6); - } - -#endif - - spi_config_gpios(dev, as_master, nssi->gpio_device, nssi->gpio_bit, - scki->gpio_device, scki->gpio_bit, - misoi->gpio_device, misoi->gpio_bit, - mosii->gpio_device, mosii->gpio_bit); + spi_config_gpios(dev, as_master, pins->nss, pins->sck, pins->miso, pins->mosi); } static const spi_baud_rate baud_rates[8] __FLASH__ = { @@ -634,6 +638,8 @@ static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) { { case RCC_APB2: clock = STM32_PCLK2; break; // 72 Mhz case RCC_APB1: clock = STM32_PCLK1; break; // 36 Mhz + case RCC_AHB1: break; + default: break; } clock /= 2; i = 0; @@ -645,5 +651,4 @@ static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq) { } -//SPIClass SPI(3); - +SPIClass SPI(3); // needed for external libs diff --git a/STM32F4/libraries/SPI/src/SPI.h b/STM32F4/libraries/SPI/src/SPI.h index 490d58b..f46795c 100644 --- a/STM32F4/libraries/SPI/src/SPI.h +++ b/STM32F4/libraries/SPI/src/SPI.h @@ -34,18 +34,16 @@ /* TODO [0.1.0] Remove deprecated methods. */ - -#ifndef _SPI_H_INCLUDED -#define _SPI_H_INCLUDED +#ifndef _LIB_SPI_H_ +#define _LIB_SPI_H_ #include #include #include - -#include -#include #include +#define SPI_DMA + // SPI_HAS_TRANSACTION means SPI has // - beginTransaction() // - endTransaction() @@ -96,34 +94,61 @@ #define SPI_MODE2 SPI_MODE_2 #define SPI_MODE3 SPI_MODE_3 +#define SPI_DATA_SIZE_8BIT SPI_CR1_DFF_8_BIT +#define SPI_DATA_SIZE_16BIT SPI_CR1_DFF_16_BIT + class SPISettings { public: SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, dataMode); + init_AlwaysInline(clock, bitOrder, dataMode, SPI_DATA_SIZE_8BIT); } else { - init_MightInline(clock, bitOrder, dataMode); + init_MightInline(clock, bitOrder, dataMode, SPI_DATA_SIZE_8BIT); } } - SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } -private: - void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { - init_AlwaysInline(clock, bitOrder, dataMode); + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode, dataSize); + } else { + init_MightInline(clock, bitOrder, dataMode, dataSize); + } } - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) { + SPISettings(uint32_t clock) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, MSBFIRST, SPI_MODE0, SPI_DATA_SIZE_8BIT); + } else { + init_MightInline(clock, MSBFIRST, SPI_MODE0, SPI_DATA_SIZE_8BIT); + } + } + SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, SPI_DATA_SIZE_8BIT); } +private: + void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { + init_AlwaysInline(clock, bitOrder, dataMode, dataSize); + } + void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) __attribute__((__always_inline__)) { this->clock = clock; this->bitOrder = bitOrder; this->dataMode = dataMode; + this->dataSize = dataSize; } uint32_t clock; BitOrder bitOrder; uint8_t dataMode; + uint32_t dataSize; + + spi_dev *spi_d; + uint32_t clockDivider; + +#ifdef SPI_DMA + dma_dev* spiDmaDev; + dma_channel spiDmaChannel; + dma_stream spiRxDmaStream, spiTxDmaStream; +#endif + friend class SPIClass; }; -volatile static bool dma1_ch3_Active; - /** * @brief Wirish SPI interface. * @@ -133,18 +158,11 @@ volatile static bool dma1_ch3_Active; class SPIClass { public: - - /** * @param spiPortNumber Number of the SPI port to manage. */ SPIClass(uint32 spiPortNumber); - /* - * Set up/tear down - */ - - /** * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). @@ -175,6 +193,8 @@ public: void beginTransaction(uint8_t pin, SPISettings settings); void endTransaction(void); + void beginTransactionSlave(SPISettings settings); + void setClockDivider(uint32_t clockDivider); void setBitOrder(BitOrder bitOrder); void setDataMode(uint8_t dataMode); @@ -195,40 +215,40 @@ public: */ /** - * @brief Return the next unread byte. + * @brief Return the next unread byte/word. * - * If there is no unread byte waiting, this function will block + * If there is no unread byte/word waiting, this function will block * until one is received. */ - uint8 read(void); + uint16 read(void); /** * @brief Read length bytes, storing them into buffer. * @param buffer Buffer to store received bytes into. - * @param length Number of bytes to store in buffer. This + * @param length Number of bytes to store in buffer. This * function will block until the desired number of * bytes have been read. */ void read(uint8 *buffer, uint32 length); /** - * @brief Transmit a byte. - * @param data Byte to transmit. - */ -// void write(uint8 data); - - /** - * @brief Transmit a half word. + * @brief Transmit one byte/word. * @param data to transmit. */ void write(uint16 data); /** - * @brief Transmit multiple bytes. - * @param buffer Bytes to transmit. - * @param length Number of bytes in buffer to transmit. + * @brief Transmit one byte/word a specified number of times. + * @param data to transmit. */ - void write(const uint8 *buffer, uint32 length); + void write(uint16 data, uint32 n); + + /** + * @brief Transmit multiple bytes/words. + * @param buffer Bytes/words to transmit. + * @param length Number of bytes/words in buffer to transmit. + */ + void write(const void * buffer, uint32 length); /** * @brief Transmit a byte, then return the next unread byte. @@ -239,9 +259,12 @@ public: * @return Next unread byte. */ uint8 transfer(uint8 data) const; + uint16_t transfer16(uint16_t data) const; +#ifdef SPI_DMA /** * @brief Sets up a DMA Transfer for "length" bytes. + * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. * * This function transmits and receives to buffers. * @@ -249,30 +272,19 @@ public: * @param receiveBuf buffer Bytes to save received data. * @param length Number of bytes in buffer to transmit. */ - uint8 dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length); + uint8 dmaTransfer(const void * transmitBuf, void * receiveBuf, uint16 length); /** - * @brief Sets up a DMA Transmit for bytes. + * @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode. + * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. * - * This function transmits and does not care about the RX fifo. - * - * @param transmitBuf buffer Bytes to transmit, - * @param length Number of bytes in buffer to transmit. - * @param minc Set to use Memory Increment mode, clear to use Circular mode. - */ - uint8 dmaSend(uint8 *transmitBuf, uint16 length, bool minc = 1); - - /** - * @brief Sets up a DMA Transmit for half words. - * SPI PERFIPHERAL MUST BE SET TO 16 BIT MODE BEFORE - * - * This function transmits and does not care about the RX fifo. + * This function only transmits and does not care about the RX fifo. * * @param data buffer half words to transmit, * @param length Number of bytes in buffer to transmit. - * @param minc Set to use Memory Increment mode (default if blank), clear to use Circular mode. */ - uint8 dmaSend(uint16 *transmitBuf, uint16 length, bool minc = 1); + uint8 dmaSend(const void * transmitBuf, uint16 length, bool minc = 1); +#endif /* * Pin accessors @@ -304,7 +316,24 @@ public: * @brief Get a pointer to the underlying libmaple spi_dev for * this HardwareSPI instance. */ - spi_dev* c_dev(void) { return this->spi_d; } + spi_dev* c_dev(void) { return _currentSetting->spi_d; } + + + spi_dev *dev(){ return _currentSetting->spi_d;} + + /** + * @brief Sets the number of the SPI peripheral to be used by + * this HardwareSPI instance. + * + * @param spi_num Number of the SPI port. 1-2 in low density devices + * or 1-3 in high density devices. + */ + + void setModule(int spi_num) + { + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed + } + /* -- The following methods are deprecated --------------------------- */ @@ -338,26 +367,13 @@ public: */ uint8 recv(void); - spi_dev *dev(){ return spi_d;} - - - private: - - static inline void DMA1_CH3_Event() { - dma1_ch3_Active = 0; -// dma_disable(DMA1, DMA_CH3); -// dma_disable(DMA1, DMA_CH2); - - // To Do. Need to wait for - } - spi_dev *spi_d; - uint8_t _SSPin; - uint32_t clockDivider; - uint8_t dataMode; - BitOrder bitOrder; + SPISettings _settings[BOARD_NR_SPI]; + SPISettings *_currentSetting; + + void updateSettings(void); }; +extern SPIClass SPI; // needed bx SdFat(EX) lib -extern SPIClass SPI;//(1);// dummy params #endif diff --git a/STM32F4/libraries/arduino_uip/library.properties b/STM32F4/libraries/arduino_uip/library.properties index d707a44..ce2c43b 100644 --- a/STM32F4/libraries/arduino_uip/library.properties +++ b/STM32F4/libraries/arduino_uip/library.properties @@ -6,6 +6,6 @@ paragraph=implements the same API as stock Ethernet-lib. Just replace the includ category=Communication url=https://github.com/ntruchsess/arduino_uip architectures=STM32F4 -version=1.04 +version=1.0.4 dependencies= core-dependencies=arduino (>=1.5.0) diff --git a/STM32F4/platform.txt b/STM32F4/platform.txt index 99ae555..3c3e833 100755 --- a/STM32F4/platform.txt +++ b/STM32F4/platform.txt @@ -8,28 +8,28 @@ version=0.1.0 # compiler variables # ---------------------- -#build.gcc_ver=gcc-arm-none-eabi-4.8.3-2014q1 - compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/ compiler.c.cmd=arm-none-eabi-gcc -compiler.c.flags=-c -g -Os -w -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.c.flags=-c -g {build.flags.optimize} -Wall -MMD -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_{build.variant} {build.vect_flags} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} compiler.c.elf.cmd=arm-none-eabi-g++ -compiler.c.elf.flags=-Os -Wl,--gc-sections +compiler.c.elf.flags={build.flags.optimize} -Wl,--gc-sections {build.flags.ldspecs} compiler.S.cmd=arm-none-eabi-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD compiler.cpp.cmd=arm-none-eabi-g++ -compiler.cpp.flags=-c -g -Os -w -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.cpp.flags=-c -g {build.flags.optimize} -Wall -MMD -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} {build.vect_flags} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} compiler.ar.cmd=arm-none-eabi-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arm-none-eabi-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 compiler.elf2hex.flags=-O binary compiler.elf2hex.cmd=arm-none-eabi-objcopy -compiler.ldflags= +compiler.ldflags={build.flags.ldspecs} compiler.size.cmd=arm-none-eabi-size compiler.define=-DARDUINO= # this can be overriden in boards.txt +build.f_cpu=168000000L +build.mcu=cortex-m4 build.cpu_flags= build.hs_flag= build.common_flags=-mthumb -D__STM32F4__ @@ -44,12 +44,10 @@ compiler.ar.extra_flags= compiler.elf2hex.extra_flags= +##compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" +#compiler.libs.c.flags="-I{build.core.path}" "-I{build.core.path}/libmaple" "-I{build.core.path}/libmaple/usbF4" "-I{build.core.path}/libmaple/usbF4/STM32_USB_Device_Library/Core/inc" "-I{build.core.path}/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc" "-I{build.core.path}/libmaple/usbF4/STM32_USB_OTG_Driver/inc" "-I{build.core.path}/libmaple/usbF4/VCP" +compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.core.path}/libmaple/usbF4" -##compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/stm32f1/include/series" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" -#compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" - - -compiler.libs.c.flags="-I{build.core.path}/libmaple" -I{build.core.path}/libmaple/usbF4 -I{build.core.path}/libmaple/usbF4/STM32_USB_Device_Library/Core/inc -I{build.core.path}/libmaple/usbF4/STM32_USB_Device_Library/Class/cdc/inc -I{build.core.path}/libmaple/usbF4/STM32_USB_OTG_Driver/inc -I{build.core.path}/libmaple/usbF4/VCP @@ -66,23 +64,22 @@ compiler.libs.c.flags="-I{build.core.path}/libmaple" -I{build.core.path}/libmapl # --------------------- ## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.cpu_flags} {build.vect_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.cpu_flags} {build.vect_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" ## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" -#recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" "{source_file}" -o "{object_file}" +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.cpu_flags} {build.vect_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" ## Create archives recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects -##recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group +##recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{archive_file_path}" -Wl,--end-group #-Wl,--entry=__start__ -#recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} -Wl,--whole-archive "{build.path}/{archive_file}" -Wl,--no-whole-archive -Wl,--end-group +#recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} "{build.variant.path}/{build.variant_system_lib}" "{archive_file_path}" -Wl,--end-group +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} -Wl,--whole-archive "{archive_file_path}" -Wl,--no-whole-archive -Wl,--end-group ## Create eeprom recipe.objcopy.eep.pattern= @@ -92,7 +89,6 @@ recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -#recipe.size.regex=\.text\s+([0-9]+).* recipe.size.regex=^(?:\.text|\.rodata|\.ARM.exidx)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* @@ -127,4 +123,3 @@ tools.stlink_upload.path.linux64={runtime.hardware.path}/tools/linux64 tools.stlink_upload.upload.params.verbose=-d tools.stlink_upload.upload.params.quiet= tools.stlink_upload.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" - diff --git a/STM32F3/cores/maple/WProgram.h b/STM32F4/system/libmaple/Arduino.h similarity index 86% rename from STM32F3/cores/maple/WProgram.h rename to STM32F4/system/libmaple/Arduino.h index b24ec2a..d445126 100644 --- a/STM32F3/cores/maple/WProgram.h +++ b/STM32F4/system/libmaple/Arduino.h @@ -24,12 +24,22 @@ * SOFTWARE. *****************************************************************************/ -#ifndef _WIRISH_WPROGRAM_H_ -#define _WIRISH_WPROGRAM_H_ +#ifndef _WIRISH_ARDUINO_H_ +#define _WIRISH_ARDUINO_H_ -#include + +#include "wirish.h" void setup(); void loop(); +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus +void yield(void); +#ifdef __cplusplus +} +#endif // __cplusplus + +#include "variant.h" #endif diff --git a/STM32F4/variants/discovery_f407/discovery_f4.cpp b/STM32F4/variants/discovery_f407/discovery_f4.cpp index d97074e..7d288d5 100644 --- a/STM32F4/variants/discovery_f407/discovery_f4.cpp +++ b/STM32F4/variants/discovery_f407/discovery_f4.cpp @@ -34,182 +34,187 @@ #include "discovery_f4.h" -//#include "fsmc.h" -#include "gpio.h" -#include "rcc.h" -#include "timer.h" +#include +#include #include "wirish_types.h" //static void initSRAMChip(void); void boardInit(void) { // remap TIMER8 to PC6-9 - gpio_set_af_mode(GPIOC, 6, 3); - gpio_set_af_mode(GPIOC, 7, 3); - gpio_set_af_mode(GPIOC, 8, 3); - gpio_set_af_mode(GPIOC, 9, 3); + gpio_set_af_mode(PC6, 3); + gpio_set_af_mode(PC7, 3); + gpio_set_af_mode(PC8, 3); + gpio_set_af_mode(PC9, 3); // remap TIMER1 to PE9,11,13,14 - gpio_set_af_mode(GPIOE, 9, 1); - gpio_set_af_mode(GPIOE, 11, 1); - gpio_set_af_mode(GPIOE, 13, 1); - gpio_set_af_mode(GPIOE, 14, 1); + gpio_set_af_mode(PE9, 1); + gpio_set_af_mode(PE11, 1); + gpio_set_af_mode(PE13, 1); + gpio_set_af_mode(PE14, 1); // remap TIMER3 to PB4,5,0,1 - gpio_set_af_mode(GPIOB, 4, 2); - gpio_set_af_mode(GPIOB, 5, 2); - gpio_set_af_mode(GPIOB, 0, 2); - gpio_set_af_mode(GPIOB, 1, 2); + gpio_set_af_mode(PB4, 2); + gpio_set_af_mode(PB5, 2); + gpio_set_af_mode(PB0, 2); + gpio_set_af_mode(PB1, 2); //gpio_set_af_mode(GPIOA, 2, 7); //gpio_set_af_mode(GPIOA, 3, 7); #ifdef ARDUINO_STM32F4_NETDUINO2PLUS // PA8 Output the Master Clock MCO1 - gpio_set_af_mode(GPIOA, 8, 0); + gpio_set_af_mode(PA8, 0); // PB4 as alternate MISO Input - gpio_set_af_mode(GPIOB, 4, 5); + gpio_set_af_mode(PB4, 5); // PA5 as alternate SCK Output - gpio_set_af_mode(GPIOA, 5, 5); + gpio_set_af_mode(PA5, 5); // PA7 as alternate MOSI Output - gpio_set_af_mode(GPIOA, 7, 5); + gpio_set_af_mode(PA7, 5); #endif return; } +extern timer_dev timer1; +extern timer_dev timer2; +extern timer_dev timer3; +extern timer_dev timer4; +extern timer_dev timer5; +extern timer_dev timer6; +extern timer_dev timer7; +extern timer_dev timer8; + #if 0 typedef struct stm32_pin_info { gpio_dev *gpio_device; /**< Maple pin's GPIO device */ timer_dev *timer_device; /**< Pin's timer device, if any. */ const adc_dev *adc_device; /**< ADC device, if any. */ - uint8 gpio_bit; /**< Pin's GPIO port bit. */ uint8 timer_channel; /**< Timer channel, or 0 if none. */ uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */ } stm32_pin_info; - #endif extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { - {GPIOA, TIMER5, ADC1, 0, 1, 0}, /* D00/PA0 */ - {GPIOA, TIMER5, ADC1, 1, 2, 1}, /* D01/PA1 */ - {GPIOA, TIMER5, ADC1, 2, 3, 2}, /* D02/PA2 */ - {GPIOA, TIMER5, ADC1, 3, 4, 3}, /* D03/PA3 */ - {GPIOA, NULL, ADC1, 4, 0, 4}, /* D04/PA4 */ - {GPIOA, NULL, ADC1, 5, 0, 5}, /* D05/PA5 */ - {GPIOA, NULL, ADC1, 6, 1, 6}, /* D06/PA6 */ // ala check TIMER3 - {GPIOA, NULL, ADC1, 7, 0, 7}, /* D07/PA7 */ - {GPIOA, NULL, NULL, 8, 0, ADCx}, /* D08/PA8 */ // remap out - {GPIOA, NULL, NULL, 9, 0, ADCx}, /* D09/PA9 */ // remap out - {GPIOA, NULL, NULL, 10, 0, ADCx}, /* D10/PA10 */ // remap out - {GPIOA, NULL, NULL, 11, 0, ADCx}, /* D11/PA11 */ // remap out - {GPIOA, NULL, NULL, 12, 0, ADCx}, /* D12/PA12 */ - {GPIOA, NULL, NULL, 13, 0, ADCx}, /* D13/PA13 */ - {GPIOA, NULL, NULL, 14, 0, ADCx}, /* D14/PA14 */ - {GPIOA, TIMER2, NULL, 15, 1, ADCx}, /* D15/PA15 */ // remap in + {&GPIOA, &timer5, &ADC1, 1, 0}, /* D00/PA0 */ + {&GPIOA, &timer5, &ADC1, 2, 1}, /* D01/PA1 */ + {&GPIOA, &timer5, &ADC1, 3, 2}, /* D02/PA2 */ + {&GPIOA, &timer5, &ADC1, 4, 3}, /* D03/PA3 */ + {&GPIOA, NULL, &ADC1, 0, 4}, /* D04/PA4 */ + {&GPIOA, NULL, &ADC1, 0, 5}, /* D05/PA5 */ + {&GPIOA, NULL, &ADC1, 1, 6}, /* D06/PA6 */ // ala check TIMER3 + {&GPIOA, NULL, &ADC1, 0, 7}, /* D07/PA7 */ + {&GPIOA, NULL, NULL, 0, ADCx}, /* D08/PA8 */ // remap out + {&GPIOA, NULL, NULL, 0, ADCx}, /* D09/PA9 */ // remap out + {&GPIOA, NULL, NULL, 0, ADCx}, /* D10/PA10 */ // remap out + {&GPIOA, NULL, NULL, 0, ADCx}, /* D11/PA11 */ // remap out + {&GPIOA, NULL, NULL, 0, ADCx}, /* D12/PA12 */ + {&GPIOA, NULL, NULL, 0, ADCx}, /* D13/PA13 */ + {&GPIOA, NULL, NULL, 0, ADCx}, /* D14/PA14 */ + {&GPIOA, &timer2, NULL, 1, ADCx}, /* D15/PA15 */ // remap in - {GPIOB, TIMER3, ADC1, 0, 3, 8}, /* D16/PB0 */ - {GPIOB, TIMER3, ADC1, 1, 4, 9}, /* D17/PB1 */ - {GPIOB, NULL, NULL, 2, 0, ADCx}, /* D18/PB2 */ - {GPIOB, TIMER2, NULL, 3, 2, ADCx}, /* D19/PB3 */ // remap in - {GPIOB, TIMER3, NULL, 4, 1, ADCx}, /* D20/PB4 */ // remap in - {GPIOB, TIMER3, NULL, 5, 2, ADCx}, /* D21/PB5 */ // remap in - {GPIOB, NULL, NULL, 6, 0, ADCx}, /* D22/PB6 */ // remap out - {GPIOB, NULL, NULL, 7, 0, ADCx}, /* D23/PB7 */ // remap out - {GPIOB, NULL, NULL, 8, 0, ADCx}, /* D24/PB8 */ // remap out - {GPIOB, NULL, NULL, 9, 0, ADCx}, /* D25/PB9 */ // remap out - {GPIOB, NULL, NULL, 10, 0, ADCx}, /* D26/PB10 */ - {GPIOB, NULL, NULL, 11, 0, ADCx}, /* D27/PB11 */ - {GPIOB, NULL, NULL, 12, 0, ADCx}, /* D28/PB12 */ - {GPIOB, NULL, NULL, 13, 0, ADCx}, /* D29/PB13 */ - {GPIOB, NULL, NULL, 14, 0, ADCx}, /* D30/PB14 */ - {GPIOB, NULL, NULL, 15, 0, ADCx}, /* D31/PB15 */ + {&GPIOB, &timer3, &ADC1, 3, 8}, /* D16/PB0 */ + {&GPIOB, &timer3, &ADC1, 4, 9}, /* D17/PB1 */ + {&GPIOB, NULL, NULL, 0, ADCx}, /* D18/PB2 */ + {&GPIOB, &timer2, NULL, 2, ADCx}, /* D19/PB3 */ // remap in + {&GPIOB, &timer3, NULL, 1, ADCx}, /* D20/PB4 */ // remap in + {&GPIOB, &timer3, NULL, 2, ADCx}, /* D21/PB5 */ // remap in + {&GPIOB, NULL, NULL, 0, ADCx}, /* D22/PB6 */ // remap out + {&GPIOB, NULL, NULL, 0, ADCx}, /* D23/PB7 */ // remap out + {&GPIOB, NULL, NULL, 0, ADCx}, /* D24/PB8 */ // remap out + {&GPIOB, NULL, NULL, 0, ADCx}, /* D25/PB9 */ // remap out + {&GPIOB, NULL, NULL, 0, ADCx}, /* D26/PB10 */ + {&GPIOB, NULL, NULL, 0, ADCx}, /* D27/PB11 */ + {&GPIOB, NULL, NULL, 0, ADCx}, /* D28/PB12 */ + {&GPIOB, NULL, NULL, 0, ADCx}, /* D29/PB13 */ + {&GPIOB, NULL, NULL, 0, ADCx}, /* D30/PB14 */ + {&GPIOB, NULL, NULL, 0, ADCx}, /* D31/PB15 */ - {GPIOC, NULL, ADC1, 0, 0, 10}, /* D32/PC0 */ - {GPIOC, NULL, ADC1, 1, 0, 11}, /* D33/PC1 */ - {GPIOC, NULL, ADC1, 2, 0, 12}, /* D34/PC2 */ - {GPIOC, NULL, ADC1, 3, 0, 13}, /* D35/PC3 */ - {GPIOC, NULL, ADC1, 4, 0, 14}, /* D36/PC4 */ - {GPIOC, NULL, ADC1, 5, 0, 15}, /* D37/PC5 */ - {GPIOC, TIMER8, NULL, 6, 1, ADCx}, /* D38/PC6 */ - {GPIOC, TIMER8, NULL, 7, 2, ADCx}, /* D39/PC7 */ - {GPIOC, TIMER8, NULL, 8, 3, ADCx}, /* D40/PC8 */ - {GPIOC, TIMER8, NULL, 9, 4, ADCx}, /* D41/PC9 */ - {GPIOC, NULL, NULL, 10, 0, ADCx}, /* D42/PC10 */ - {GPIOC, NULL, NULL, 11, 0, ADCx}, /* D43/PC11 */ - {GPIOC, NULL, NULL, 12, 0, ADCx}, /* D44/PC12 */ - {GPIOC, NULL, NULL, 13, 0, ADCx}, /* D45/PC13 */ - {GPIOC, NULL, NULL, 14, 0, ADCx}, /* D46/PC14 */ - {GPIOC, NULL, NULL, 15, 0, ADCx}, /* D47/PC15 */ + {&GPIOC, NULL, &ADC1, 0, 10}, /* D32/PC0 */ + {&GPIOC, NULL, &ADC1, 0, 11}, /* D33/PC1 */ + {&GPIOC, NULL, &ADC1, 0, 12}, /* D34/PC2 */ + {&GPIOC, NULL, &ADC1, 0, 13}, /* D35/PC3 */ + {&GPIOC, NULL, &ADC1, 0, 14}, /* D36/PC4 */ + {&GPIOC, NULL, &ADC1, 0, 15}, /* D37/PC5 */ + {&GPIOC, &timer8, NULL, 1, ADCx}, /* D38/PC6 */ + {&GPIOC, &timer8, NULL, 2, ADCx}, /* D39/PC7 */ + {&GPIOC, &timer8, NULL, 3, ADCx}, /* D40/PC8 */ + {&GPIOC, &timer8, NULL, 4, ADCx}, /* D41/PC9 */ + {&GPIOC, NULL, NULL, 0, ADCx}, /* D42/PC10 */ + {&GPIOC, NULL, NULL, 0, ADCx}, /* D43/PC11 */ + {&GPIOC, NULL, NULL, 0, ADCx}, /* D44/PC12 */ + {&GPIOC, NULL, NULL, 0, ADCx}, /* D45/PC13 */ + {&GPIOC, NULL, NULL, 0, ADCx}, /* D46/PC14 */ + {&GPIOC, NULL, NULL, 0, ADCx}, /* D47/PC15 */ - {GPIOD, NULL, NULL, 0, 0, ADCx}, /* D48/PD0 */ - {GPIOD, NULL, NULL, 1, 0, ADCx}, /* D49/PD1 */ - {GPIOD, NULL, NULL, 2, 0, ADCx}, /* D50/PD2 */ - {GPIOD, NULL, NULL, 3, 0, ADCx}, /* D51/PD3 */ - {GPIOD, NULL, NULL, 4, 0, ADCx}, /* D52/PD4 */ - {GPIOD, NULL, NULL, 5, 0, ADCx}, /* D53/PD5 */ - {GPIOD, NULL, NULL, 6, 0, ADCx}, /* D54/PD6 */ - {GPIOD, NULL, NULL, 7, 0, ADCx}, /* D55/PD7 */ - {GPIOD, NULL, NULL, 8, 0, ADCx}, /* D56/PD8 */ - {GPIOD, NULL, NULL, 9, 0, ADCx}, /* D57/PD9 */ - {GPIOD, NULL, NULL, 10, 0, ADCx}, /* D58/PD10 */ - {GPIOD, NULL, NULL, 11, 0, ADCx}, /* D59/PD11 */ - {GPIOD, TIMER4, NULL, 12, 1, ADCx}, /* D60/PD12 */ // remap in - {GPIOD, TIMER4, NULL, 13, 2, ADCx}, /* D61/PD13 */ // remap in - {GPIOD, TIMER4, NULL, 14, 3, ADCx}, /* D62/PD14 */ // remap in - {GPIOD, TIMER4, NULL, 15, 4, ADCx}, /* D63/PD15 */ // remap in + {&GPIOD, NULL, NULL, 0, ADCx}, /* D48/PD0 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D49/PD1 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D50/PD2 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D51/PD3 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D52/PD4 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D53/PD5 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D54/PD6 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D55/PD7 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D56/PD8 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D57/PD9 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D58/PD10 */ + {&GPIOD, NULL, NULL, 0, ADCx}, /* D59/PD11 */ + {&GPIOD, &timer4, NULL, 1, ADCx}, /* D60/PD12 */ // remap in + {&GPIOD, &timer4, NULL, 2, ADCx}, /* D61/PD13 */ // remap in + {&GPIOD, &timer4, NULL, 3, ADCx}, /* D62/PD14 */ // remap in + {&GPIOD, &timer4, NULL, 4, ADCx}, /* D63/PD15 */ // remap in - {GPIOE, NULL, NULL, 0, 0, ADCx}, /* D64/PE0 */ - {GPIOE, NULL, NULL, 1, 0, ADCx}, /* D65/PE1 */ - {GPIOE, NULL, NULL, 2, 0, ADCx}, /* D66/PE2 */ - {GPIOE, NULL, NULL, 3, 0, ADCx}, /* D67/PE3 */ - {GPIOE, NULL, NULL, 4, 0, ADCx}, /* D68/PE4 */ - {GPIOE, NULL, NULL, 5, 0, ADCx}, /* D69/PE5 */ - {GPIOE, NULL, NULL, 6, 0, ADCx}, /* D70/PE6 */ - {GPIOE, NULL, NULL, 7, 0, ADCx}, /* D71/PE7 */ - {GPIOE, NULL, NULL, 8, 0, ADCx}, /* D72/PE8 */ - {GPIOE, TIMER1, NULL, 9, 1, ADCx}, /* D73/PE9 */ // remap in - {GPIOE, NULL, NULL, 10, 0, ADCx}, /* D74/PE10 */ - {GPIOE, TIMER1, NULL, 11, 2, ADCx}, /* D75/PE11 */ // remap in - {GPIOE, NULL, NULL, 12, 0, ADCx}, /* D76/PE12 */ - {GPIOE, TIMER1, NULL, 13, 3, ADCx}, /* D77/PE13 */ // remap in - {GPIOE, TIMER1, NULL, 14, 4, ADCx}, /* D78/PE14 */ // remap in - {GPIOE, NULL, NULL, 15, 0, ADCx}, /* D79/PE15 */ - - {GPIOF, NULL, NULL, 0, 0, ADCx}, /* D80/PF0 */ - {GPIOF, NULL, NULL, 1, 0, ADCx}, /* D81/PF1 */ - {GPIOF, NULL, NULL, 2, 0, ADCx}, /* D82/PF2 */ - {GPIOF, NULL, NULL, 3, 0, ADCx}, /* D83/PF3 */ - {GPIOF, NULL, NULL, 4, 0, ADCx}, /* D84/PF4 */ - {GPIOF, NULL, NULL, 5, 0, ADCx}, /* D85/PF5 */ - {GPIOF, NULL, NULL, 6, 0, ADCx}, /* D86/PF6 */ - {GPIOF, NULL, NULL, 7, 0, ADCx}, /* D87/PF7 */ - {GPIOF, NULL, NULL, 8, 0, ADCx}, /* D88/PF8 */ - {GPIOF, NULL, NULL, 9, 0, ADCx}, /* D89/PF9 */ - {GPIOF, NULL, NULL, 10, 0, ADCx}, /* D90/PF10 */ - {GPIOF, NULL, NULL, 11, 0, ADCx}, /* D91/PF11 */ - {GPIOF, NULL, NULL, 12, 0, ADCx}, /* D92/PF12 */ - {GPIOF, NULL, NULL, 13, 0, ADCx}, /* D93/PF13 */ - {GPIOF, NULL, NULL, 14, 0, ADCx}, /* D94/PF14 */ - {GPIOF, NULL, NULL, 15, 0, ADCx}, /* D95/PF15 */ - - {GPIOG, NULL, NULL, 0, 0, ADCx}, /* D96/PG0 */ - {GPIOG, NULL, NULL, 1, 0, ADCx}, /* D97/PG1 */ - {GPIOG, NULL, NULL, 2, 0, ADCx}, /* D98/PG2 */ - {GPIOG, NULL, NULL, 3, 0, ADCx}, /* D99/PG3 */ - {GPIOG, NULL, NULL, 4, 0, ADCx}, /* D100/PG4 */ - {GPIOG, NULL, NULL, 5, 0, ADCx}, /* D101/PG5 */ - {GPIOG, NULL, NULL, 6, 0, ADCx}, /* D102/PG6 */ - {GPIOG, NULL, NULL, 7, 0, ADCx}, /* D103/PG7 */ - {GPIOG, NULL, NULL, 8, 0, ADCx}, /* D104/PG8 */ - {GPIOG, NULL, NULL, 9, 0, ADCx}, /* D105/PG9 */ - {GPIOG, NULL, NULL, 10, 0, ADCx}, /* D106/PG10 */ - {GPIOG, NULL, NULL, 11, 0, ADCx}, /* D107/PG11 */ - {GPIOG, NULL, NULL, 12, 0, ADCx}, /* D108/PG12 */ - {GPIOG, NULL, NULL, 13, 0, ADCx}, /* D109/PG13 */ - {GPIOG, NULL, NULL, 14, 0, ADCx}, /* D110/PG14 */ - {GPIOG, NULL, NULL, 15, 0, ADCx} /* D111/PG15 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D64/PE0 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D65/PE1 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D66/PE2 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D67/PE3 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D68/PE4 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D69/PE5 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D70/PE6 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D71/PE7 */ + {&GPIOE, NULL, NULL, 0, ADCx}, /* D72/PE8 */ + {&GPIOE, &timer1, NULL, 1, ADCx}, /* D73/PE9 */ // remap in + {&GPIOE, NULL, NULL, 0, ADCx}, /* D74/PE10 */ + {&GPIOE, &timer1, NULL, 2, ADCx}, /* D75/PE11 */ // remap in + {&GPIOE, NULL, NULL, 0, ADCx}, /* D76/PE12 */ + {&GPIOE, &timer1, NULL, 3, ADCx}, /* D77/PE13 */ // remap in + {&GPIOE, &timer1, NULL, 4, ADCx}, /* D78/PE14 */ // remap in + {&GPIOE, NULL, NULL, 0, ADCx}, /* D79/PE15 */ +#if 0 // not available on LQFP100 package + {&GPIOF, NULL, NULL, 0, ADCx}, /* D80/PF0 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D81/PF1 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D82/PF2 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D83/PF3 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D84/PF4 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D85/PF5 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D86/PF6 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D87/PF7 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D88/PF8 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D89/PF9 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D90/PF10 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D91/PF11 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D92/PF12 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D93/PF13 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D94/PF14 */ + {&GPIOF, NULL, NULL, 0, ADCx}, /* D95/PF15 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D96/PG0 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D97/PG1 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D98/PG2 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D99/PG3 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D100/PG4 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D101/PG5 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D102/PG6 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D103/PG7 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D104/PG8 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D105/PG9 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D106/PG10 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D107/PG11 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D108/PG12 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D109/PG13 */ + {&GPIOG, NULL, NULL, 0, ADCx}, /* D110/PG14 */ + {&GPIOG, NULL, NULL, 0, ADCx} /* D111/PG15 */ +#endif // not available on LQFP100 package }; extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { diff --git a/STM32F4/variants/discovery_f407/discovery_f4.h b/STM32F4/variants/discovery_f407/discovery_f4.h index 7501752..e3fa046 100644 --- a/STM32F4/variants/discovery_f407/discovery_f4.h +++ b/STM32F4/variants/discovery_f407/discovery_f4.h @@ -50,6 +50,9 @@ #define BOARD_LED_PIN Port2Pin('D', 12) #define BOARD_BUTTON_PIN Port2Pin('A', 0) +#define BOARD_USB_DM_PIN PA11 +#define BOARD_USB_DP_PIN PA12 + #define BOARD_NR_USARTS 5 #define BOARD_USART1_TX_PIN Port2Pin('A', 9) #define BOARD_USART1_RX_PIN Port2Pin('A',10) diff --git a/STM32F4/variants/discovery_f407/variant.h b/STM32F4/variants/discovery_f407/variant.h index 8a88623..8782ccc 100644 --- a/STM32F4/variants/discovery_f407/variant.h +++ b/STM32F4/variants/discovery_f407/variant.h @@ -2,7 +2,7 @@ #define _VARIANT_ARDUINO_STM32_ #define digitalPinToPort(P) ( PIN_MAP[P].gpio_device ) -#define digitalPinToBitMask(P) ( BIT(PIN_MAP[P].gpio_bit) ) +#define digitalPinToBitMask(P) ( BIT(P&0x0F) ) #define portOutputRegister(port) ( &(port->regs->ODR) ) #define portInputRegister(port) ( &(port->regs->IDR) ) diff --git a/STM32F4/variants/generic_f407v/generic_f407v.cpp b/STM32F4/variants/generic_f407v/generic_f407v.cpp new file mode 100644 index 0000000..c51ff9b --- /dev/null +++ b/STM32F4/variants/generic_f407v/generic_f407v.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file generic_f407v.cpp + * @author ala42 + * @brief generic_f407v board file. + */ + +#ifdef BOARD_generic_f407v + +#include "generic_f407v.h" + +#include "wirish_types.h" + +//static void initSRAMChip(void); +/*****************************************************************************/ +// Alternate functions, see DocID022152 Rev 8, Table 9. +/*****************************************************************************/ +void boardInit(void) { +/* // remap TIMER8 to PC6-9 + gpio_set_af_mode(GPIOC, 6, 3); + gpio_set_af_mode(GPIOC, 7, 3); + gpio_set_af_mode(GPIOC, 8, 3); + gpio_set_af_mode(GPIOC, 9, 3); + + // remap TIMER1 to PE9,11,13,14 + gpio_set_af_mode(GPIOE, 9, 1); + gpio_set_af_mode(GPIOE, 11, 1); + gpio_set_af_mode(GPIOE, 13, 1); + gpio_set_af_mode(GPIOE, 14, 1); + + // remap TIMER3 to PB4,5,0,1 + gpio_set_af_mode(GPIOB, 4, 2); + gpio_set_af_mode(GPIOB, 5, 2); + gpio_set_af_mode(GPIOB, 0, 2); + gpio_set_af_mode(GPIOB, 1, 2); + + //gpio_set_af_mode(GPIOA, 2, 7); + //gpio_set_af_mode(GPIOA, 3, 7); +*/ + return; +} + +/* +static void initSRAMChip(void) { + fsmc_nor_psram_reg_map *regs = FSMC_NOR_PSRAM1_BASE; + + fsmc_sram_init_gpios(); + rcc_clk_enable(RCC_FSMC); + + regs->BCR = (FSMC_BCR_WREN | FSMC_BCR_MWID_16BITS | FSMC_BCR_MTYP_SRAM | + FSMC_BCR_MBKEN); + fsmc_nor_psram_set_addset(regs, 0); + fsmc_nor_psram_set_datast(regs, 3); +} +*/ +#endif diff --git a/STM32F4/variants/generic_f407v/generic_f407v.h b/STM32F4/variants/generic_f407v/generic_f407v.h new file mode 100644 index 0000000..bc3b77b --- /dev/null +++ b/STM32F4/variants/generic_f407v/generic_f407v.h @@ -0,0 +1,192 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file generic_f407v.h + * @author Marti Bolivar + * @brief Private include file for Maple Native in boards.h + * + * See maple.h for more information on these definitions. + */ + +#ifndef _BOARD_GENERIC_F407V_H_ +#define _BOARD_GENERIC_F407V_H_ + +#define Port2Pin(port, bit) ((port-'A')*16+bit) + +#define CYCLES_PER_MICROSECOND 168 + + +#undef STM32_PCLK1 +#undef STM32_PCLK2 +#define STM32_PCLK1 (CYCLES_PER_MICROSECOND*1000000/4) +#define STM32_PCLK2 (CYCLES_PER_MICROSECOND*1000000/2) + +#define SYSTICK_RELOAD_VAL (CYCLES_PER_MICROSECOND*1000-1) + +/*****************************************************************************/ +// Board pin definitions +#define BOARD_USB_DM_PIN PA11 +#define BOARD_USB_DP_PIN PA12 + +#define BOARD_LED_PIN PA6 //Port2Pin('A', 6) +#define BOARD_LED2_PIN PA7 //Port2Pin('A', 7) +#define BOARD_BUTTON1_PIN PA0 //Port2Pin('A', 0) +#define BOARD_BUTTON2_PIN PE4 //Port2Pin('E', 4) +#define BOARD_BUTTON3_PIN PE3 //Port2Pin('E', 3) + +#define BOARD_NR_USARTS 5 +#define BOARD_USART1_TX_PIN PA9 //Port2Pin('A', 9) +#define BOARD_USART1_RX_PIN PA10 //Port2Pin('A',10) +#define BOARD_USART2_TX_PIN PA2 //Port2Pin('A', 2) +#define BOARD_USART2_RX_PIN PA3 //Port2Pin('A', 3) +#define BOARD_USART3_TX_PIN PB10 //Port2Pin('B',10) +#define BOARD_USART3_RX_PIN PB11 //Port2Pin('B',11) +#define BOARD_UART4_TX_PIN PA0 //Port2Pin('A', 0) +#define BOARD_UART4_RX_PIN PA1 //Port2Pin('A', 1) +#define BOARD_UART5_TX_PIN PC12 //Port2Pin('C',12) +#define BOARD_UART5_RX_PIN PD2 //Port2Pin('D', 2) + +#define BOARD_NR_SPI 3 +#define BOARD_SPI1_NSS_PIN PA4 //Port2Pin('A', 4) +#define BOARD_SPI1_SCK_PIN PA5 //Port2Pin('A', 5) +#define BOARD_SPI1_MISO_PIN PA6 //Port2Pin('A', 6) +#define BOARD_SPI1_MOSI_PIN PA7 //Port2Pin('A', 7) +#define BOARD_SPI1A_NSS_PIN PA15 //Port2Pin('A',15) +#define BOARD_SPI1A_SCK_PIN PB3 //Port2Pin('B', 3) +#define BOARD_SPI1A_MISO_PIN PB4 //Port2Pin('B', 4) +#define BOARD_SPI1A_MOSI_PIN PB5 //Port2Pin('B', 5) + +#define BOARD_SPI2_NSS_PIN PB12 //Port2Pin('B',12) +#define BOARD_SPI2_SCK_PIN PB13 //Port2Pin('B',13) +#define BOARD_SPI2_MISO_PIN PB14 //Port2Pin('B',14) +#define BOARD_SPI2_MOSI_PIN PB15 //Port2Pin('B',15) +#define BOARD_SPI2A_NSS_PIN PB9 //Port2Pin('B', 9) +#define BOARD_SPI2A_SCK_PIN PB10 //Port2Pin('B',10) +#define BOARD_SPI2A_MISO_PIN PC2 //Port2Pin('C', 2) +#define BOARD_SPI2A_MOSI_PIN PC3 //Port2Pin('C', 3) + +#define BOARD_SPI3_NSS_PIN PA15 //Port2Pin('A',15) +#define BOARD_SPI3_SCK_PIN PB3 //Port2Pin('B', 3) +#define BOARD_SPI3_MISO_PIN PB4 //Port2Pin('B', 4) +#define BOARD_SPI3_MOSI_PIN PB5 //Port2Pin('B', 5) +/* overlap with the SDIO interface for SD card +#define BOARD_SPI3A_NSS_PIN PA4 //Port2Pin('A', 4) +#define BOARD_SPI3A_SCK_PIN PC10 //Port2Pin('C',10) +#define BOARD_SPI3A_MISO_PIN PC11 //Port2Pin('C',11) +#define BOARD_SPI3A_MOSI_PIN PC12 //Port2Pin('C',12) +*/ +#define BOARD_SDIO_D0 PC8 //Port2Pin('C', 8) +#define BOARD_SDIO_D1 PC9 //Port2Pin('C', 9) +#define BOARD_SDIO_D2 PC10 //Port2Pin('C',10) +#define BOARD_SDIO_D3 PC11 //Port2Pin('C',11) +#define BOARD_SDIO_CLK PC12 //Port2Pin('C',12) +#define BOARD_SDIO_CMD PD2 //Port2Pin('D', 2) + +#define FSMC_NOE PD4 +#define FSMC_NWE PD5 +#define FSMC_NE1 PD7 +#define FSMC_A18 PD13 +#define FSMC_A17 PD12 +#define FSMC_A16 PD11 +#define FSMC_D0 PD14 +#define FSMC_D1 PD15 +#define FSMC_D2 PD0 +#define FSMC_D3 PD1 +#define FSMC_D4 PE7 +#define FSMC_D5 PE8 +#define FSMC_D6 PE9 +#define FSMC_D7 PE10 +#define FSMC_D8 PE11 +#define FSMC_D9 PE12 +#define FSMC_D10 PE13 +#define FSMC_D11 PE14 +#define FSMC_D12 PE15 +#define FSMC_D13 PD8 +#define FSMC_D14 PD9 +#define FSMC_D15 PD10 + +#define BOARD_T_CS BOARD_SPI2_NSS_PIN +#define BOARD_T_SCK BOARD_SPI2_SCK_PIN +#define BOARD_T_MISO BOARD_SPI2_MISO_PIN +#define BOARD_T_MOSI BOARD_SPI2_MOSI_PIN +#define BOARD_T_PEN PC5 + +#define BOARD_NR_GPIO_PINS 80 +#define BOARD_NR_PWM_PINS 22 +#define BOARD_NR_ADC_PINS 16 +#define BOARD_NR_USED_PINS 22 +#define BOARD_JTMS_SWDIO_PIN PA13 //Port2Pin('A',13) +#define BOARD_JTCK_SWCLK_PIN PA14 //Port2Pin('A',14) +#define BOARD_JTDI_PIN PA15 //Port2Pin('A',15) +#define BOARD_JTDO_PIN PB3 //Port2Pin('B', 3) +#define BOARD_NJTRST_PIN PB4 //Port2Pin('B', 4) + +/*****************************************************************************/ +// Pins reserved for the on-board hardware +#define USB_DM_PIN BOARD_USB_DM_PIN // PA11 +#define USB_DP_PIN BOARD_USB_DP_PIN // PA12 + +#define FLASH_CS_PIN PB0 +#define FLASH_CLK_PIN BOARD_SPI3_SCK_PIN // PB3 +#define FLASH_DO_PIN BOARD_SPI3_MISO_PIN // PB4 +#define FLASH_DI_PIN BOARD_SPI3_MOSI_PIN // PB5 + +#define NRF24_CLK_PIN BOARD_SPI3_SCK_PIN // PB3 +#define NRF24_DO_PIN BOARD_SPI3_MISO_PIN // PB4 +#define NRF24_DI_PIN BOARD_SPI3_MOSI_PIN // PB5 +#define NRF24_CE_PIN PB6 +#define NRF24_CS_PIN PB7 +#define NRF24_IRQ_PIN PB8 + +// SD card, SDIO mode +#define SD_DAT0 BOARD_SDIO_D0 // PC8 +#define SD_DAT1 BOARD_SDIO_D1 // PC9 +#define SD_DAT2 BOARD_SDIO_D2 // PC10 +#define SD_DAT3 BOARD_SDIO_D3 // PC11 +#define SD_CLK BOARD_SDIO_CK // PC12 +#define SD_CMD BOARD_SDIO_CMD // PD2 +// SD card, SPI mode, only usable with software SPI +#define SD_DI BOARD_SDIO_CMD // PD2 +#define SD_DO BOARD_SDIO_D0 // PC8 +#define SD_CS BOARD_SDIO_D3 // PC11 +#define SD_SCLK BOARD_SDIO_CK // PC12 + +/*****************************************************************************/ + +enum { +PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7,PA8,PA9,PA10,PA11,PA12,PA13,PA14,PA15, +PB0,PB1,PB2,PB3,PB4,PB5,PB6,PB7,PB8,PB9,PB10,PB11,PB12,PB13,PB14,PB15, +PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PC8,PC9,PC10,PC11,PC12,PC13,PC14,PC15, +PD0,PD1,PD2,PD3,PD4,PD5,PD6,PD7,PD8,PD9,PD10,PD11,PD12,PD13,PD14,PD15, +PE0,PE1,PE2,PE3,PE4,PE5,PE6,PE7,PE8,PE9,PE10,PE11,PE12,PE13,PE14,PE15, +#if 0 // not available on LQFP100 package +PF0,PF1,PF2,PF3,PF4,PF5,PF6,PF7,PF8,PF9,PF10,PF11,PF12,PF13,PF14,PF15, +PG0,PG1,PG2,PG3,PG4,PG5,PG6,PG7,PG8,PG9,PG10,PG11,PG12,PG13,PG14,PG15 +#endif // not available on LQFP100 package +}; + +#endif diff --git a/STM32F4/variants/generic_f407v/ld/bootloader_8004000.ld b/STM32F4/variants/generic_f407v/ld/bootloader_8004000.ld new file mode 100644 index 0000000..677683e --- /dev/null +++ b/STM32F4/variants/generic_f407v/ld/bootloader_8004000.ld @@ -0,0 +1,21 @@ +/* + * STM32F4xx high density linker script for + * JTAG (bare metal, no bootloader) builds. + */ + +MEMORY +{ + ccmram (rw): ORIGIN = 0x10000000, LENGTH = 64K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K + rom (rx) : ORIGIN = 0x08004000, LENGTH = 496K +} + +/* GROUP(libcs3_stm32_high_density.a) */ + +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +_FLASH_BUILD = 1; +INCLUDE common.inc diff --git a/STM32F3/variants/discovery_f3/ld/common.inc b/STM32F4/variants/generic_f407v/ld/common.inc similarity index 98% rename from STM32F3/variants/discovery_f3/ld/common.inc rename to STM32F4/variants/generic_f407v/ld/common.inc index 49aaf6f..30c49c2 100644 --- a/STM32F3/variants/discovery_f3/ld/common.inc +++ b/STM32F4/variants/generic_f407v/ld/common.inc @@ -182,17 +182,16 @@ SECTIONS _end = __bss_end__; } > REGION_BSS - /* - * .ccm - */ - .ccm (NOLOAD) : - { - . = ALIGN(4); - *(.CCM) - . = ALIGN(4); - } > REGION_CCM - /* + * .ccmram + */ + .ccmram (NOLOAD): + { + . = ALIGN(8); + *(.ccmram .ccmram.*) + } > ccmram + + /* * Debugging sections */ .stab 0 (NOLOAD) : { *(.stab) } diff --git a/STM32F4/variants/generic_f407v/ld/extra_libs.inc b/STM32F4/variants/generic_f407v/ld/extra_libs.inc new file mode 100644 index 0000000..dd2c84f --- /dev/null +++ b/STM32F4/variants/generic_f407v/ld/extra_libs.inc @@ -0,0 +1,7 @@ +/* + * Extra archives needed by ARM's GCC ARM Embedded arm-none-eabi- + * releases (https://launchpad.net/gcc-arm-embedded/). + */ + +/* This is for the provided newlib. */ +GROUP(libnosys.a) diff --git a/STM32F4/variants/generic_f407v/ld/flash.ld b/STM32F4/variants/generic_f407v/ld/flash.ld new file mode 100644 index 0000000..c753a78 --- /dev/null +++ b/STM32F4/variants/generic_f407v/ld/flash.ld @@ -0,0 +1,20 @@ +/* + * Discovery F4 (STM32F407VGT6, high density) linker script for + * Flash builds. + */ + +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 125K + rom (rx) : ORIGIN = 0x08010000, LENGTH = 960K /* ala42 */ +} + +/* GROUP(libcs4_stm32_high_density.a) */ + +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +_FLASH_BUILD = 1; +INCLUDE common.inc diff --git a/STM32F4/variants/generic_f407v/ld/jtag.ld b/STM32F4/variants/generic_f407v/ld/jtag.ld new file mode 100644 index 0000000..2156f15 --- /dev/null +++ b/STM32F4/variants/generic_f407v/ld/jtag.ld @@ -0,0 +1,21 @@ +/* + * STM32F4xx high density linker script for + * JTAG (bare metal, no bootloader) builds. + */ + +MEMORY +{ + ccmram (rw): ORIGIN = 0x10000000, LENGTH = 64K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K +} + +/* GROUP(libcs3_stm32_high_density.a) */ + +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +_FLASH_BUILD = 1; +INCLUDE common.inc diff --git a/STM32F3/variants/discovery_f3/ld/names.inc b/STM32F4/variants/generic_f407v/ld/names.inc similarity index 100% rename from STM32F3/variants/discovery_f3/ld/names.inc rename to STM32F4/variants/generic_f407v/ld/names.inc diff --git a/STM32F4/variants/generic_f407v/ld/ram.ld b/STM32F4/variants/generic_f407v/ld/ram.ld new file mode 100644 index 0000000..b57060c --- /dev/null +++ b/STM32F4/variants/generic_f407v/ld/ram.ld @@ -0,0 +1,19 @@ +/* + * aeroquad32 (STM32F103VET6, high density) linker script for + * RAM builds. + */ + +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K + rom (rx) : ORIGIN = 0x08010000, LENGTH = 0K /* ala42 */ +} + +GROUP(libcs3_stm32_high_density.a) + +REGION_ALIAS("REGION_TEXT", ram); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", ram); + +INCLUDE common.inc diff --git a/STM32F4/variants/generic_f407v/ld/vector_symbols.inc b/STM32F4/variants/generic_f407v/ld/vector_symbols.inc new file mode 100644 index 0000000..f8519bb --- /dev/null +++ b/STM32F4/variants/generic_f407v/ld/vector_symbols.inc @@ -0,0 +1,78 @@ +EXTERN(__msp_init) +EXTERN(__exc_reset) +EXTERN(__exc_nmi) +EXTERN(__exc_hardfault) +EXTERN(__exc_memmanage) +EXTERN(__exc_busfault) +EXTERN(__exc_usagefault) +EXTERN(__stm32reservedexception7) +EXTERN(__stm32reservedexception8) +EXTERN(__stm32reservedexception9) +EXTERN(__stm32reservedexception10) +EXTERN(__exc_svc) +EXTERN(__exc_debug_monitor) +EXTERN(__stm32reservedexception13) +EXTERN(__exc_pendsv) +EXTERN(__exc_systick) + +EXTERN(__irq_wwdg) +EXTERN(__irq_pvd) +EXTERN(__irq_tamper) +EXTERN(__irq_rtc) +EXTERN(__irq_flash) +EXTERN(__irq_rcc) +EXTERN(__irq_exti0) +EXTERN(__irq_exti1) +EXTERN(__irq_exti2) +EXTERN(__irq_exti3) +EXTERN(__irq_exti4) +EXTERN(__irq_dma1_channel1) +EXTERN(__irq_dma1_channel2) +EXTERN(__irq_dma1_channel3) +EXTERN(__irq_dma1_channel4) +EXTERN(__irq_dma1_channel5) +EXTERN(__irq_dma1_channel6) +EXTERN(__irq_dma1_channel7) +EXTERN(__irq_adc) +EXTERN(__irq_usb_hp_can_tx) +EXTERN(__irq_usb_lp_can_rx0) +EXTERN(__irq_can_rx1) +EXTERN(__irq_can_sce) +EXTERN(__irq_exti9_5) +EXTERN(__irq_tim1_brk) +EXTERN(__irq_tim1_up) +EXTERN(__irq_tim1_trg_com) +EXTERN(__irq_tim1_cc) +EXTERN(__irq_tim2) +EXTERN(__irq_tim3) +EXTERN(__irq_tim4) +EXTERN(__irq_i2c1_ev) +EXTERN(__irq_i2c1_er) +EXTERN(__irq_i2c2_ev) +EXTERN(__irq_i2c2_er) +EXTERN(__irq_spi1) +EXTERN(__irq_spi2) +EXTERN(__irq_usart1) +EXTERN(__irq_usart2) +EXTERN(__irq_usart3) +EXTERN(__irq_exti15_10) +EXTERN(__irq_rtcalarm) +EXTERN(__irq_usbwakeup) + +EXTERN(__irq_tim8_brk) +EXTERN(__irq_tim8_up) +EXTERN(__irq_tim8_trg_com) +EXTERN(__irq_tim8_cc) +EXTERN(__irq_adc3) +EXTERN(__irq_fsmc) +EXTERN(__irq_sdio) +EXTERN(__irq_tim5) +EXTERN(__irq_spi3) +EXTERN(__irq_uart4) +EXTERN(__irq_uart5) +EXTERN(__irq_tim6) +EXTERN(__irq_tim7) +EXTERN(__irq_dma2_channel1) +EXTERN(__irq_dma2_channel2) +EXTERN(__irq_dma2_channel3) +EXTERN(__irq_dma2_channel4_5) diff --git a/STM32F4/variants/generic_f407v/pin_map.c b/STM32F4/variants/generic_f407v/pin_map.c new file mode 100644 index 0000000..db5247b --- /dev/null +++ b/STM32F4/variants/generic_f407v/pin_map.c @@ -0,0 +1,210 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file generic_f407v.cpp + * @author ala42 + * @brief generic_f407v board file. + */ + +#ifdef BOARD_generic_f407v + +#ifdef __cplusplus +extern "C"{ +#endif + +//#include "generic_f407v.h" + +//#include "fsmc.h" +#include +#include +#include + +#include + +extern timer_dev timer1; +extern timer_dev timer2; +extern timer_dev timer3; +extern timer_dev timer4; +extern timer_dev timer5; +extern timer_dev timer6; +extern timer_dev timer7; +extern timer_dev timer8; + +/* +typedef struct stm32_pin_info { + gpio_dev *gpio_device; // Maple pin's GPIO device + timer_dev *timer_device; // Pin's timer device, if any. + uint8 timer_channel; // Timer channel, or 0 if none. + uint8 adc_channel; // Pin ADC channel, or ADCx if none. + const adc_dev *adc_device; // ADC device, if any. +} stm32_pin_info; +*/ +const stm32_pin_info PIN_MAP[] = { // LQFP100 package pin + {&GPIOA, &timer5, 1, 0, &ADC1}, // D00/PA0 | 23 | USART2_CTS | UART4_TX | ETH_MII_CRS | TIM2_CH1_ETR | TIM5_CH1 | TIM8_ETR | ADC123_IN0/WKUP + {&GPIOA, &timer5, 2, 1, &ADC1}, // D01/PA1 | 24 | USART2_RTS | UART4_RX | ETH_RMII_REF_CLK | ETH_MII_RX_CLK | TIM5_CH2 | TIM2_CH2 | ADC123_IN1 + {&GPIOA, &timer5, 3, 2, &ADC1}, // D02/PA2 | 25 | USART2_TX | TIM5_CH3 | TIM9_CH1 | TIM2_CH3 | ETH_MDIO | ADC123_IN2 + {&GPIOA, &timer5, 4, 3, &ADC1}, // D03/PA3 | 26 | USART2_RX | TIM5_CH4 | TIM9_CH2 | TIM2_CH4 | OTG_HS_ULPI_D0 | ETH_MII_COL | ADC123_IN3 + {&GPIOA, NULL, 0, 4, &ADC1}, // D04/PA4 | 29 | SPI1_NSS | SPI3_NSS | USART2_CK | DCMI_HSYNC | OTG_HS_SOF | I2S3_WS | ADC12_IN4 / DAC_OUT1 + {&GPIOA, NULL, 0, 5, &ADC1}, // D05/PA5 | 30 | SPI1_SCK | OTG_HS_ULPI_CK | TIM2_CH1_ETR | TIM8_CH1N | ADC12_IN5 / DAC_OUT2 + {&GPIOA, NULL, 1, 6, &ADC1}, // D06/PA6 | 31 | SPI1_MISO | TIM8_BKIN | TIM13_CH1 | DCMI_PIXCLK | TIM3_CH1 | TIM1_BKIN | ADC12_IN6 + {&GPIOA, NULL, 0, 7, &ADC1}, // D07/PA7 | 32 | SPI1_MOSI | TIM8_CH1N | TIM14_CH1 | TIM3_CH2 | ETH_MII_RX_DV | TIM1_CH1N / ETH_RMII_CRS_DV | ADC12_IN7 + {&GPIOA, NULL, 0, ADCx, NULL}, // D08/PA8 | 67 | MCO1 | USART1_CK | TIM1_CH1 | I2C3_SCL | OTG_FS_SOF + {&GPIOA, NULL, 0, ADCx, NULL}, // D09/PA9 | 68 | USART1_TX | TIM1_CH2 | I2C3_SMBA | DCMI_D0 + {&GPIOA, NULL, 0, ADCx, NULL}, // D10/PA10 | 69 | USART1_RX | TIM1_CH3 | OTG_FS_ID | DCMI_D1 + {&GPIOA, NULL, 0, ADCx, NULL}, // D11/PA11 | 70 | USART1_CTS | CAN1_RX | TIM1_CH4 | OTG_FS_DM + {&GPIOA, NULL, 0, ADCx, NULL}, // D12/PA12 | 71 | USART1_RTS | CAN1_TX | TIM1_ETR | OTG_FS_DP + {&GPIOA, NULL, 0, ADCx, NULL}, // D13/PA13 | 72 | JTMS-SWDIO + {&GPIOA, NULL, 0, ADCx, NULL}, // D14/PA14 | 76 | JTCK-SWCLK + {&GPIOA, &timer2, 1, ADCx, NULL}, // D15/PA15 | 77 | JTDI | SPI3_NSS | I2S3_WS | TIM2_CH1_ETR | SPI1_NSS + + {&GPIOB, &timer3, 3, 8, &ADC1}, // D16/PB0 | 35 | TIM3_CH3 | TIM8_CH2N | OTG_HS_ULPI_D1 | ETH_MII_RXD2 | TIM1_CH2N | ADC12_IN8 + {&GPIOB, &timer3, 4, 9, &ADC1}, // D17/PB1 | 36 | TIM3_CH4 | TIM8_CH3N | OTG_HS_ULPI_D2 | ETH_MII_RXD3 | TIM1_CH3N | ADC12_IN9 + {&GPIOB, NULL, 0, ADCx, NULL}, // D18/PB2 | 37 | BOOT1 + {&GPIOB, &timer2, 2, ADCx, NULL}, // D19/PB3 | 89 | JTDO | TRACESWO | SPI3_SCK | I2S3_CK | TIM2_CH2 | SPI1_SCK + {&GPIOB, &timer3, 1, ADCx, NULL}, // D20/PB4 | 90 | NJTRST | SPI3_MISO | TIM3_CH1 | SPI1_MISO | I2S3ext_SD + {&GPIOB, &timer3, 2, ADCx, NULL}, // D21/PB5 | 91 | I2C1_SMBA | CAN2_RX | OTG_HS_ULPI_D7 | ETH_PPS_OUT | TIM3_CH2 | SPI1_MOSI | SPI3_MOSI | DCMI_D10 | I2S3_SD + {&GPIOB, NULL, 0, ADCx, NULL}, // D22/PB6 | 92 | I2C1_SCL | TIM4_CH1 | CAN2_TX | DCMI_D5 | USART1_TX + {&GPIOB, NULL, 0, ADCx, NULL}, // D23/PB7 | 93 | I2C1_SDA | FSMC_NL | DCMI_VSYNC | USART1_RX | TIM4_CH2 + {&GPIOB, NULL, 0, ADCx, NULL}, // D24/PB8 | 95 | TIM4_CH3 | SDIO_D4 | TIM10_CH1 | DCMI_D6 | ETH_MII_TXD3 | I2C1_SCL | CAN1_RX + {&GPIOB, NULL, 0, ADCx, NULL}, // D25/PB9 | 96 | SPI2_NSS | I2S2_WS | TIM4_CH4 | TIM11_CH1 | SDIO_D5 | DCMI_D7 | I2C1_SDA | CAN1_TX + {&GPIOB, NULL, 0, ADCx, NULL}, // D26/PB10 | 47 | SPI2_SCK | I2S2_CK | I2C2_SCL | USART3_TX | OTG_HS_ULPI_D3 | ETH_MII_RX_ER | TIM2_CH3 + {&GPIOB, NULL, 0, ADCx, NULL}, // D27/PB11 | 48 | I2C2_SDA | USART3_RX | OTG_HS_ULPI_D4 | ETH_RMII_TX_EN | ETH_MII_TX_EN | TIM2_CH4 + {&GPIOB, NULL, 0, ADCx, NULL}, // D28/PB12 | 51 | SPI2_NSS | I2S2_WS | I2C2_SMBA | USART3_CK | TIM1_BKIN | CAN2_RX | OTG_HS_ULPI_D5 | ETH_RMII_TXD0 | ETH_MII_TXD0 | OTG_HS_ID + {&GPIOB, NULL, 0, ADCx, NULL}, // D29/PB13 | 52 | SPI2_SCK | I2S2_CK | USART3_CTS | TIM1_CH1N | CAN2_TX | OTG_HS_ULPI_D6 | ETH_RMII_TXD1 | ETH_MII_TXD1 + {&GPIOB, NULL, 0, ADCx, NULL}, // D30/PB14 | 53 | SPI2_MISO | TIM1_CH2N | TIM12_CH1 | OTG_HS_DM | USART3_RTS | TIM8_CH2N | I2S2ext_SD + {&GPIOB, NULL, 0, ADCx, NULL}, // D31/PB15 | 54 | SPI2_MOSI | I2S2_SD | TIM1_CH3N | TIM8_CH3N | TIM12_CH2 | OTG_HS_DP + + {&GPIOC, NULL, 0, 10, &ADC1}, // D32/PC0 | 15 | OTG_HS_ULPI_STP | ADC123_IN10 + {&GPIOC, NULL, 0, 11, &ADC1}, // D33/PC1 | 16 | ETH_MDC | ADC123_IN11 + {&GPIOC, NULL, 0, 12, &ADC1}, // D34/PC2 | 17 | SPI2_MISO | OTG_HS_ULPI_DIR | ETH_MII_TXD2 | I2S2ext_SD | ADC123_IN12 + {&GPIOC, NULL, 0, 13, &ADC1}, // D35/PC3 | 18 | SPI2_MOSI | I2S2_SD | OTG_HS_ULPI_NXT | ETH_MII_TX_CLK | ADC123_IN13 + {&GPIOC, NULL, 0, 14, &ADC1}, // D36/PC4 | 33 | ETH_RMII_RX_D0 | ETH_MII_RX_D0 | ADC12_IN14 + {&GPIOC, NULL, 0, 15, &ADC1}, // D37/PC5 | 34 | ETH_RMII_RX_D1 | ETH_MII_RX_D1 | ADC12_IN15 + {&GPIOC, &timer8, 1, ADCx, NULL}, // D38/PC6 | 63 | I2S2_MCK | TIM8_CH1/SDIO_D6 | USART6_TX | DCMI_D0/TIM3_CH1 + {&GPIOC, &timer8, 2, ADCx, NULL}, // D39/PC7 | 64 | I2S3_MCK | TIM8_CH2/SDIO_D7 | USART6_RX | DCMI_D1/TIM3_CH2 + {&GPIOC, &timer8, 3, ADCx, NULL}, // D40/PC8 | 65 | TIM8_CH3 | SDIO_D0 | TIM3_CH3 | USART6_CK | DCMI_D2 + {&GPIOC, &timer8, 4, ADCx, NULL}, // D41/PC9 | 66 | I2S_CKIN | MCO2 | TIM8_CH4 | SDIO_D1 | I2C3_SDA | DCMI_D3 | TIM3_CH4 + {&GPIOC, NULL, 0, ADCx, NULL}, // D42/PC10 | 78 | SPI3_SCK | I2S3_CK | UART4_TX | SDIO_D2 | DCMI_D8 | USART3_TX + {&GPIOC, NULL, 0, ADCx, NULL}, // D43/PC11 | 79 | UART4_RX | SPI3_MISO | SDIO_D3 | DCMI_D4 | USART3_RX | I2S3ext_SD + {&GPIOC, NULL, 0, ADCx, NULL}, // D44/PC12 | 80 | UART5_TX | SDIO_CK | DCMI_D9 | SPI3_MOSI | I2S3_SD | USART3_CK + {&GPIOC, NULL, 0, ADCx, NULL}, // D45/PC13 | 7 | RTC_OUT, RTC_TAMP1, RTC_TS + {&GPIOC, NULL, 0, ADCx, NULL}, // D46/PC14 | 8 | OSC32_IN + {&GPIOC, NULL, 0, ADCx, NULL}, // D47/PC15 | 9 | OSC32_OUT + + {&GPIOD, NULL, 0, ADCx, NULL}, // D48/PD0 | 81 | FSMC_D2 | CAN1_RX + {&GPIOD, NULL, 0, ADCx, NULL}, // D49/PD1 | 82 | FSMC_D3 | CAN1_TX + {&GPIOD, NULL, 0, ADCx, NULL}, // D50/PD2 | 83 | TIM3_ETR | UART5_RX | SDIO_CMD | DCMI_D11 + {&GPIOD, NULL, 0, ADCx, NULL}, // D51/PD3 | 84 | FSMC_CLK | USART2_CTS + {&GPIOD, NULL, 0, ADCx, NULL}, // D52/PD4 | 85 | FSMC_NOE | USART2_RTS + {&GPIOD, NULL, 0, ADCx, NULL}, // D53/PD5 | 86 | FSMC_NWE | USART2_TX + {&GPIOD, NULL, 0, ADCx, NULL}, // D54/PD6 | 87 | FSMC_NWAIT | USART2_RX + {&GPIOD, NULL, 0, ADCx, NULL}, // D55/PD7 | 88 | USART2_CK | FSMC_NE1 | FSMC_NCE2 + {&GPIOD, NULL, 0, ADCx, NULL}, // D56/PD8 | 55 | FSMC_D13 | USART3_TX + {&GPIOD, NULL, 0, ADCx, NULL}, // D57/PD9 | 56 | FSMC_D14 | USART3_RX + {&GPIOD, NULL, 0, ADCx, NULL}, // D58/PD10 | 57 | FSMC_D15 | USART3_CK + {&GPIOD, NULL, 0, ADCx, NULL}, // D59/PD11 | 58 | FSMC_CLE | FSMC_A16 | USART3_CTS + {&GPIOD, &timer4, 1, ADCx, NULL}, // D60/PD12 | 59 | FSMC_ALE | FSMC_A17 | TIM4_CH1 | USART3_RTS // remap in + {&GPIOD, &timer4, 2, ADCx, NULL}, // D61/PD13 | 60 | FSMC_A18 | TIM4_CH2 // remap in + {&GPIOD, &timer4, 3, ADCx, NULL}, // D62/PD14 | 61 | FSMC_D0 | TIM4_CH3 // remap in + {&GPIOD, &timer4, 4, ADCx, NULL}, // D63/PD15 | 62 | FSMC_D1 | TIM4_CH4 // remap in + + {&GPIOE, NULL, 0, ADCx, NULL}, // D64/PE0 | 97 | TIM4_ETR | FSMC_NBL0 | DCMI_D2 + {&GPIOE, NULL, 0, ADCx, NULL}, // D65/PE1 | 98 | FSMC_NBL1 | DCMI_D3 + {&GPIOE, NULL, 0, ADCx, NULL}, // D66/PE2 | 1 | TRACECLK | FSMC_A23 | ETH_MII_TXD3 + {&GPIOE, NULL, 0, ADCx, NULL}, // D67/PE3 | 2 | TRACED0 | FSMC_A19 + {&GPIOE, NULL, 0, ADCx, NULL}, // D68/PE4 | 3 | TRACED1 | FSMC_A20 | DCMI_D4 + {&GPIOE, NULL, 0, ADCx, NULL}, // D69/PE5 | 4 | TRACED2 | FSMC_A21 | TIM9_CH1 / DCMI_D6 + {&GPIOE, NULL, 0, ADCx, NULL}, // D70/PE6 | 5 | TRACED3 | FSMC_A22 | TIM9_CH2 / DCMI_D7 + {&GPIOE, NULL, 0, ADCx, NULL}, // D71/PE7 | 38 | FSMC_D4 | TIM1_ETR + {&GPIOE, NULL, 0, ADCx, NULL}, // D72/PE8 | 39 | FSMC_D5 | TIM1_CH1N + {&GPIOE, &timer1, 1, ADCx, NULL}, // D73/PE9 | 40 | FSMC_D6 | TIM1_CH1 // remap in + {&GPIOE, NULL, 0, ADCx, NULL}, // D74/PE10 | 41 | FSMC_D7 | TIM1_CH2N + {&GPIOE, &timer1, 2, ADCx, NULL}, // D75/PE11 | 42 | FSMC_D8 | TIM1_CH2 // remap in + {&GPIOE, NULL, 0, ADCx, NULL}, // D76/PE12 | 43 | FSMC_D9 | TIM1_CH3N + {&GPIOE, &timer1, 3, ADCx, NULL}, // D77/PE13 | 44 | FSMC_D10 | TIM1_CH3 // remap in + {&GPIOE, &timer1, 4, ADCx, NULL}, // D78/PE14 | 45 | FSMC_D11 | TIM1_CH4 // remap in + {&GPIOE, NULL, 0, ADCx, NULL}, // D79/PE15 | 46 | FSMC_D12 | TIM1_BKIN +#if 0 + {GPIOF, 0, NULL, 0, NULL, ADCx}, // D80/PF0 + {GPIOF, 1, NULL, 0, NULL, ADCx}, // D81/PF1 + {GPIOF, 2, NULL, 0, NULL, ADCx}, // D82/PF2 + {GPIOF, 3, NULL, 0, NULL, ADCx}, // D83/PF3 + {GPIOF, 4, NULL, 0, NULL, ADCx}, // D84/PF4 + {GPIOF, 5, NULL, 0, NULL, ADCx}, // D85/PF5 + {GPIOF, 6, NULL, 0, NULL, ADCx}, // D86/PF6 + {GPIOF, 7, NULL, 0, NULL, ADCx}, // D87/PF7 + {GPIOF, 8, NULL, 0, NULL, ADCx}, // D88/PF8 + {GPIOF, 9, NULL, 0, NULL, ADCx}, // D89/PF9 + {GPIOF, 10, NULL, 0, NULL, ADCx}, // D90/PF10 + {GPIOF, 11, NULL, 0, NULL, ADCx}, // D91/PF11 + {GPIOF, 12, NULL, 0, NULL, ADCx}, // D92/PF12 + {GPIOF, 13, NULL, 0, NULL, ADCx}, // D93/PF13 + {GPIOF, 14, NULL, 0, NULL, ADCx}, // D94/PF14 + {GPIOF, 15, NULL, 0, NULL, ADCx}, // D95/PF15 + + {GPIOG, 0, NULL, 0, NULL, ADCx}, // D96/PG0 + {GPIOG, 1, NULL, 0, NULL, ADCx}, // D97/PG1 + {GPIOG, 2, NULL, 0, NULL, ADCx}, // D98/PG2 + {GPIOG, 3, NULL, 0, NULL, ADCx}, // D99/PG3 + {GPIOG, 4, NULL, 0, NULL, ADCx}, // D100/PG4 + {GPIOG, 5, NULL, 0, NULL, ADCx}, // D101/PG5 + {GPIOG, 6, NULL, 0, NULL, ADCx}, // D102/PG6 + {GPIOG, 7, NULL, 0, NULL, ADCx}, // D103/PG7 + {GPIOG, 8, NULL, 0, NULL, ADCx}, // D104/PG8 + {GPIOG, 9, NULL, 0, NULL, ADCx}, // D105/PG9 + {GPIOG, 10, NULL, 0, NULL, ADCx}, // D106/PG10 + {GPIOG, 11, NULL, 0, NULL, ADCx}, // D107/PG11 + {GPIOG, 12, NULL, 0, NULL, ADCx}, // D108/PG12 + {GPIOG, 13, NULL, 0, NULL, ADCx}, // D109/PG13 + {GPIOG, 14, NULL, 0, NULL, ADCx}, // D110/PG14 + {GPIOG, 15, NULL, 0, NULL, ADCx} // D111/PG15 +#endif +}; +/* to be defined +extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { + 0, 1, 2, 3, 15, 16, 17, 19, 20, 21, 38, 39, 49, 41, 60, 61, 62, 63, 73, 75, 77, 78 +}; +*/ +const uint8 boardADCPins[BOARD_NR_ADC_PINS] = { + PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PB0, PB1, PC0, PC1, PC2, PC3, PC4, PC5 +}; + +const uint8 boardUsedPins[BOARD_NR_USED_PINS] = { + BOARD_LED_PIN, BOARD_LED2_PIN, BOARD_BUTTON1_PIN, BOARD_BUTTON2_PIN, BOARD_BUTTON2_PIN, + BOARD_JTMS_SWDIO_PIN, BOARD_JTCK_SWCLK_PIN, + FLASH_CS_PIN, FLASH_CLK_PIN, FLASH_DO_PIN, FLASH_DI_PIN, + NRF24_CE_PIN, NRF24_CS_PIN, NRF24_IRQ_PIN, + BOARD_SDIO_D0, BOARD_SDIO_D1, BOARD_SDIO_D2, BOARD_SDIO_D3, BOARD_SDIO_CLK, BOARD_SDIO_CMD, + USB_DM_PIN, USB_DP_PIN +}; + +#ifdef __cplusplus +} +#endif + + +#endif // BOARD_generic_f407v diff --git a/STM32F4/variants/generic_f407v/pins_arduino.h b/STM32F4/variants/generic_f407v/pins_arduino.h new file mode 100644 index 0000000..3052f2e --- /dev/null +++ b/STM32F4/variants/generic_f407v/pins_arduino.h @@ -0,0 +1,6 @@ + + + + +// API compatibility +#include "variant.h" \ No newline at end of file diff --git a/STM32F4/variants/generic_f407v/stm32_isrs.S b/STM32F4/variants/generic_f407v/stm32_isrs.S new file mode 100644 index 0000000..34e515c --- /dev/null +++ b/STM32F4/variants/generic_f407v/stm32_isrs.S @@ -0,0 +1,323 @@ +/* STM32 ISR weak declarations */ + + .thumb + +/* Default handler for all non-overridden interrupts and exceptions */ + .globl __default_handler + .type __default_handler, %function + +__default_handler: + b . + + .weak __exc_nmi + .globl __exc_nmi + .set __exc_nmi, __default_handler + .weak __exc_hardfault + .globl __exc_hardfault + .set __exc_hardfault, __default_handler + .weak __exc_memmanage + .globl __exc_memmanage + .set __exc_memmanage, __default_handler + .weak __exc_busfault + .globl __exc_busfault + .set __exc_busfault, __default_handler + .weak __exc_usagefault + .globl __exc_usagefault + .set __exc_usagefault, __default_handler + .weak __stm32reservedexception7 + .globl __stm32reservedexception7 + .set __stm32reservedexception7, __default_handler + .weak __stm32reservedexception8 + .globl __stm32reservedexception8 + .set __stm32reservedexception8, __default_handler + .weak __stm32reservedexception9 + .globl __stm32reservedexception9 + .set __stm32reservedexception9, __default_handler + .weak __stm32reservedexception10 + .globl __stm32reservedexception10 + .set __stm32reservedexception10, __default_handler + .weak __exc_svc + .globl __exc_svc + .set __exc_svc, __default_handler + .weak __exc_debug_monitor + .globl __exc_debug_monitor + .set __exc_debug_monitor, __default_handler + .weak __stm32reservedexception13 + .globl __stm32reservedexception13 + .set __stm32reservedexception13, __default_handler + .weak __exc_pendsv + .globl __exc_pendsv + .set __exc_pendsv, __default_handler + .weak __exc_systick + .globl __exc_systick + .set __exc_systick, __default_handler + .weak __irq_wwdg + .globl __irq_wwdg + .set __irq_wwdg, __default_handler + .weak __irq_pvd + .globl __irq_pvd + .set __irq_pvd, __default_handler + .weak __irq_tamper + .globl __irq_tamper + .set __irq_tamper, __default_handler + .weak __irq_rtc + .globl __irq_rtc + .set __irq_rtc, __default_handler + .weak __irq_flash + .globl __irq_flash + .set __irq_flash, __default_handler + .weak __irq_rcc + .globl __irq_rcc + .set __irq_rcc, __default_handler + .weak __irq_exti0 + .globl __irq_exti0 + .set __irq_exti0, __default_handler + .weak __irq_exti1 + .globl __irq_exti1 + .set __irq_exti1, __default_handler + .weak __irq_exti2 + .globl __irq_exti2 + .set __irq_exti2, __default_handler + .weak __irq_exti3 + .globl __irq_exti3 + .set __irq_exti3, __default_handler + .weak __irq_exti4 + .globl __irq_exti4 + .set __irq_exti4, __default_handler + .weak __irq_dma1_channel1 + .globl __irq_dma1_channel1 + .set __irq_dma1_channel1, __default_handler + .weak __irq_dma1_channel2 + .globl __irq_dma1_channel2 + .set __irq_dma1_channel2, __default_handler + .weak __irq_dma1_channel3 + .globl __irq_dma1_channel3 + .set __irq_dma1_channel3, __default_handler + .weak __irq_dma1_channel4 + .globl __irq_dma1_channel4 + .set __irq_dma1_channel4, __default_handler + .weak __irq_dma1_channel5 + .globl __irq_dma1_channel5 + .set __irq_dma1_channel5, __default_handler + .weak __irq_dma1_channel6 + .globl __irq_dma1_channel6 + .set __irq_dma1_channel6, __default_handler + .weak __irq_dma1_channel7 + .globl __irq_dma1_channel7 + .set __irq_dma1_channel7, __default_handler + .weak __irq_adc + .globl __irq_adc + .set __irq_adc, __default_handler + .weak __irq_usb_hp_can_tx + .globl __irq_usb_hp_can_tx + .set __irq_usb_hp_can_tx, __default_handler + .weak __irq_usb_lp_can_rx0 + .globl __irq_usb_lp_can_rx0 + .set __irq_usb_lp_can_rx0, __default_handler + .weak __irq_can_rx1 + .globl __irq_can_rx1 + .set __irq_can_rx1, __default_handler + .weak __irq_can_sce + .globl __irq_can_sce + .set __irq_can_sce, __default_handler + .weak __irq_exti9_5 + .globl __irq_exti9_5 + .set __irq_exti9_5, __default_handler + .weak __irq_tim1_brk + .globl __irq_tim1_brk + .set __irq_tim1_brk, __default_handler + .weak __irq_tim1_up + .globl __irq_tim1_up + .set __irq_tim1_up, __default_handler + .weak __irq_tim1_trg_com + .globl __irq_tim1_trg_com + .set __irq_tim1_trg_com, __default_handler + .weak __irq_tim1_cc + .globl __irq_tim1_cc + .set __irq_tim1_cc, __default_handler + .weak __irq_tim2 + .globl __irq_tim2 + .set __irq_tim2, __default_handler + .weak __irq_tim3 + .globl __irq_tim3 + .set __irq_tim3, __default_handler + .weak __irq_tim4 + .globl __irq_tim4 + .set __irq_tim4, __default_handler + .weak __irq_i2c1_ev + .globl __irq_i2c1_ev + .set __irq_i2c1_ev, __default_handler + .weak __irq_i2c1_er + .globl __irq_i2c1_er + .set __irq_i2c1_er, __default_handler + .weak __irq_i2c2_ev + .globl __irq_i2c2_ev + .set __irq_i2c2_ev, __default_handler + .weak __irq_i2c2_er + .globl __irq_i2c2_er + .set __irq_i2c2_er, __default_handler + .weak __irq_spi1 + .globl __irq_spi1 + .set __irq_spi1, __default_handler + .weak __irq_spi2 + .globl __irq_spi2 + .set __irq_spi2, __default_handler + .weak __irq_usart1 + .globl __irq_usart1 + .set __irq_usart1, __default_handler + .weak __irq_usart2 + .globl __irq_usart2 + .set __irq_usart2, __default_handler + .weak __irq_usart3 + .globl __irq_usart3 + .set __irq_usart3, __default_handler + .weak __irq_exti15_10 + .globl __irq_exti15_10 + .set __irq_exti15_10, __default_handler + .weak __irq_rtcalarm + .globl __irq_rtcalarm + .set __irq_rtcalarm, __default_handler + .weak __irq_usbwakeup + .globl __irq_usbwakeup + .set __irq_usbwakeup, __default_handler +#if defined (STM32_HIGH_DENSITY) + .weak __irq_tim8_brk + .globl __irq_tim8_brk + .set __irq_tim8_brk, __default_handler + .weak __irq_tim8_up + .globl __irq_tim8_up + .set __irq_tim8_up, __default_handler + .weak __irq_tim8_trg_com + .globl __irq_tim8_trg_com + .set __irq_tim8_trg_com, __default_handler + .weak __irq_tim8_cc + .globl __irq_tim8_cc + .set __irq_tim8_cc, __default_handler + .weak __irq_adc3 + .globl __irq_adc3 + .set __irq_adc3, __default_handler + .weak __irq_fsmc + .globl __irq_fsmc + .set __irq_fsmc, __default_handler + .weak __irq_sdio + .globl __irq_sdio + .set __irq_sdio, __default_handler + .weak __irq_tim5 + .globl __irq_tim5 + .set __irq_tim5, __default_handler + .weak __irq_spi3 + .globl __irq_spi3 + .set __irq_spi3, __default_handler + .weak __irq_uart4 + .globl __irq_uart4 + .set __irq_uart4, __default_handler + .weak __irq_uart5 + .globl __irq_uart5 + .set __irq_uart5, __default_handler + .weak __irq_tim6 + .globl __irq_tim6 + .set __irq_tim6, __default_handler + .weak __irq_tim7 + .globl __irq_tim7 + .set __irq_tim7, __default_handler + .weak __irq_dma2_channel1 + .globl __irq_dma2_channel1 + .set __irq_dma2_channel1, __default_handler + .weak __irq_dma2_channel2 + .globl __irq_dma2_channel2 + .set __irq_dma2_channel2, __default_handler + .weak __irq_dma2_channel3 + .globl __irq_dma2_channel3 + .set __irq_dma2_channel3, __default_handler + .weak __irq_dma2_channel4_5 + .globl __irq_dma2_channel4_5 + .set __irq_dma2_channel4_5, __default_handler +#endif /* STM32_HIGH_DENSITY */ + + .weak __irq_DMA2_Stream4_IRQHandler + .globl __irq_DMA2_Stream4_IRQHandler + .set __irq_DMA2_Stream4_IRQHandler, __default_handler + + .weak __irq_ETH_IRQHandler + .globl __irq_ETH_IRQHandler + .set __irq_ETH_IRQHandler, __default_handler + + .weak __irq_ETH_WKUP_IRQHandler + .globl __irq_ETH_WKUP_IRQHandler + .set __irq_ETH_WKUP_IRQHandler, __default_handler + + .weak __irq_CAN2_TX_IRQHandler + .globl __irq_CAN2_TX_IRQHandler + .set __irq_CAN2_TX_IRQHandler, __default_handler + + .weak __irq_CAN2_RX0_IRQHandler + .globl __irq_CAN2_RX0_IRQHandler + .set __irq_CAN2_RX0_IRQHandler, __default_handler + + .weak __irq_CAN2_RX1_IRQHandler + .globl __irq_CAN2_RX1_IRQHandler + .set __irq_CAN2_RX1_IRQHandler, __default_handler + + .weak __irq_CAN2_SCE_IRQHandler + .globl __irq_CAN2_SCE_IRQHandler + .set __irq_CAN2_SCE_IRQHandler, __default_handler + + .weak __irq_OTG_FS_IRQHandler + .globl __irq_OTG_FS_IRQHandler + .set __irq_OTG_FS_IRQHandler, __default_handler + + .weak __irq_DMA2_Stream5_IRQHandler + .globl __irq_DMA2_Stream5_IRQHandler + .set __irq_DMA2_Stream5_IRQHandler, __default_handler + + .weak __irq_DMA2_Stream6_IRQHandler + .globl __irq_DMA2_Stream6_IRQHandler + .set __irq_DMA2_Stream6_IRQHandler, __default_handler + + .weak __irq_DMA2_Stream7_IRQHandler + .globl __irq_DMA2_Stream7_IRQHandler + .set __irq_DMA2_Stream7_IRQHandler, __default_handler + + .weak __irq_USART6_IRQHandler + .globl __irq_USART6_IRQHandler + .set __irq_USART6_IRQHandler, __default_handler + + .weak __irq_I2C3_EV_IRQHandler + .globl __irq_I2C3_EV_IRQHandler + .set __irq_I2C3_EV_IRQHandler, __default_handler + + .weak __irq_I2C3_ER_IRQHandler + .globl __irq_I2C3_ER_IRQHandler + .set __irq_I2C3_ER_IRQHandler, __default_handler + + .weak __irq_OTG_HS_EP1_OUT_IRQHandler + .globl __irq_OTG_HS_EP1_OUT_IRQHandler + .set __irq_OTG_HS_EP1_OUT_IRQHandler, __default_handler + + .weak __irq_OTG_HS_EP1_IN_IRQHandler + .globl __irq_OTG_HS_EP1_IN_IRQHandler + .set __irq_OTG_HS_EP1_IN_IRQHandler, __default_handler + + .weak __irq_OTG_HS_WKUP_IRQHandler + .globl __irq_OTG_HS_WKUP_IRQHandler + .set __irq_OTG_HS_WKUP_IRQHandler, __default_handler + + .weak __irq_OTG_HS_IRQHandler + .globl __irq_OTG_HS_IRQHandler + .set __irq_OTG_HS_IRQHandler, __default_handler + + .weak __irq_DCMI_IRQHandler + .globl __irq_DCMI_IRQHandler + .set __irq_DCMI_IRQHandler, __default_handler + + .weak __irq_CRYP_IRQHandler + .globl __irq_CRYP_IRQHandler + .set __irq_CRYP_IRQHandler, __default_handler + + .weak __irq_HASH_RNG_IRQHandler + .globl __irq_HASH_RNG_IRQHandler + .set __irq_HASH_RNG_IRQHandler, __default_handler + + .weak __irq_FPU_IRQHandler + .globl __irq_FPU_IRQHandler + .set __irq_FPU_IRQHandler, __default_handler diff --git a/STM32F4/variants/generic_f407v/stm32_vector_table.S b/STM32F4/variants/generic_f407v/stm32_vector_table.S new file mode 100644 index 0000000..9f08d66 --- /dev/null +++ b/STM32F4/variants/generic_f407v/stm32_vector_table.S @@ -0,0 +1,113 @@ +/* STM32 vector table */ + + .section ".stm32.interrupt_vector" + + .globl __stm32_vector_table + .type __stm32_vector_table, %object + +__stm32_vector_table: +/* CM3 core interrupts */ + .long __msp_init + .long __exc_reset + .long __exc_nmi + .long __exc_hardfault + .long __exc_memmanage + .long __exc_busfault + .long __exc_usagefault + .long __stm32reservedexception7 + .long __stm32reservedexception8 + .long __stm32reservedexception9 + .long __stm32reservedexception10 + .long __exc_svc + .long __exc_debug_monitor + .long __stm32reservedexception13 + .long __exc_pendsv + .long __exc_systick +/* Peripheral interrupts */ + .long __irq_wwdg + .long __irq_pvd + .long __irq_tamper + .long __irq_rtc + .long __irq_flash + .long __irq_rcc + .long __irq_exti0 + .long __irq_exti1 + .long __irq_exti2 + .long __irq_exti3 + .long __irq_exti4 + .long __irq_dma1_channel1 + .long __irq_dma1_channel2 + .long __irq_dma1_channel3 + .long __irq_dma1_channel4 + .long __irq_dma1_channel5 + .long __irq_dma1_channel6 + .long __irq_dma1_channel7 + .long __irq_adc + .long __irq_usb_hp_can_tx + .long __irq_usb_lp_can_rx0 + .long __irq_can_rx1 + .long __irq_can_sce + .long __irq_exti9_5 + .long __irq_tim1_brk + .long __irq_tim1_up + .long __irq_tim1_trg_com + .long __irq_tim1_cc + .long __irq_tim2 + .long __irq_tim3 + .long __irq_tim4 + .long __irq_i2c1_ev + .long __irq_i2c1_er + .long __irq_i2c2_ev + .long __irq_i2c2_er + .long __irq_spi1 + .long __irq_spi2 + .long __irq_usart1 + .long __irq_usart2 + .long __irq_usart3 + .long __irq_exti15_10 + .long __irq_rtcalarm + .long __irq_usbwakeup +#if defined (STM32_HIGH_DENSITY) + .long __irq_tim8_brk + .long __irq_tim8_up + .long __irq_tim8_trg_com + .long __irq_tim8_cc + .long __irq_adc3 + .long __irq_fsmc + .long __irq_sdio + .long __irq_tim5 + .long __irq_spi3 + .long __irq_uart4 + .long __irq_uart5 + .long __irq_tim6 + .long __irq_tim7 + .long __irq_dma2_channel1 + .long __irq_dma2_channel2 + .long __irq_dma2_channel3 + .long __irq_dma2_channel4_5 +#endif /* STM32_HIGH_DENSITY */ + + .long __irq_DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .long __irq_ETH_IRQHandler /* Ethernet */ + .long __irq_ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .long __irq_CAN2_TX_IRQHandler /* CAN2 TX */ + .long __irq_CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .long __irq_CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .long __irq_CAN2_SCE_IRQHandler /* CAN2 SCE */ + .long __irq_OTG_FS_IRQHandler /* USB OTG FS */ + .long __irq_DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .long __irq_DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .long __irq_DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .long __irq_USART6_IRQHandler /* USART6 */ + .long __irq_I2C3_EV_IRQHandler /* I2C3 event */ + .long __irq_I2C3_ER_IRQHandler /* I2C3 error */ + .long __irq_OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .long __irq_OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .long __irq_OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .long __irq_OTG_HS_IRQHandler /* USB OTG HS */ + .long __irq_DCMI_IRQHandler /* DCMI */ + .long __irq_CRYP_IRQHandler /* CRYP crypto */ + .long __irq_HASH_RNG_IRQHandler /* Hash and Rng */ + .long __irq_FPU_IRQHandler /* FPU */ + + .size __stm32_vector_table, . - __stm32_vector_table diff --git a/STM32F4/variants/generic_f407v/variant.h b/STM32F4/variants/generic_f407v/variant.h new file mode 100644 index 0000000..95a7f39 --- /dev/null +++ b/STM32F4/variants/generic_f407v/variant.h @@ -0,0 +1,21 @@ +#ifndef _VARIANT_ARDUINO_STM32_ +#define _VARIANT_ARDUINO_STM32_ + + +#define digitalPinToPort(P) ( PIN_MAP[P].gpio_device ) +#define digitalPinToBitMask(P) ( BIT(P&0x0F) ) +#define portOutputRegister(port) ( &(port->regs->ODR) ) +#define portInputRegister(port) ( &(port->regs->IDR) ) + +#define portSetRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BSRR) ) +#define portClearRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BRR) ) + +#define portConfigRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->CRL) ) + +static const uint8_t SS = BOARD_SPI1_NSS_PIN; +static const uint8_t SS1 = BOARD_SPI2_NSS_PIN; +static const uint8_t MOSI = BOARD_SPI1_MOSI_PIN; +static const uint8_t MISO = BOARD_SPI1_MISO_PIN; +static const uint8_t SCK = BOARD_SPI1_SCK_PIN; + +#endif /* _VARIANT_ARDUINO_STM32_ */ \ No newline at end of file diff --git a/STM32F3/cores/maple/libmaple/include/libmaple/delay.h b/STM32F4/variants/generic_f407v/wirish/start.S similarity index 55% rename from STM32F3/cores/maple/libmaple/include/libmaple/delay.h rename to STM32F4/variants/generic_f407v/wirish/start.S index 472a208..8b181aa 100644 --- a/STM32F3/cores/maple/libmaple/include/libmaple/delay.h +++ b/STM32F4/variants/generic_f407v/wirish/start.S @@ -1,7 +1,6 @@ /****************************************************************************** * The MIT License * - * Copyright (c) 2010 Perry Hung. * Copyright (c) 2011 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person @@ -25,41 +24,34 @@ * SOFTWARE. *****************************************************************************/ -/** - * @file libmaple/include/libmaple/delay.h - * @brief Delay implementation - */ - -#ifndef _LIBMAPLE_DELAY_H_ -#define _LIBMAPLE_DELAY_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * @brief Delay the given number of microseconds. +/* + * This file is a modified version of a file obtained from + * CodeSourcery Inc. (now part of Mentor Graphics Corp.), in which the + * following text appeared: * - * @param us Number of microseconds to delay. + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. */ -static inline void delay_us(uint32 us) { - us *= STM32_DELAY_US_MULT; - /* fudge for function call overhead */ - us--; - asm volatile(" mov r0, %[us] \n\t" - "1: subs r0, #1 \n\t" - " bhi 1b \n\t" - : - : [us] "r" (us) - : "r0"); -} + .text + .code 16 + .thumb_func -#ifdef __cplusplus -} -#endif - -#endif + .globl __start__ + .type __start__, %function +__start__: + .fnstart + ldr r1,=__msp_init + mov sp,r1 + ldr r1,=start_c + bx r1 + .pool + .cantunwind + .fnend diff --git a/STM32F4/variants/generic_f407v/wirish/start_c.c b/STM32F4/variants/generic_f407v/wirish/start_c.c new file mode 100644 index 0000000..655fefb --- /dev/null +++ b/STM32F4/variants/generic_f407v/wirish/start_c.c @@ -0,0 +1,95 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * This file is a modified version of a file obtained from + * CodeSourcery Inc. (now part of Mentor Graphics Corp.), in which the + * following text appeared: + * + * Copyright (c) 2006, 2007 CodeSourcery Inc + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#include + +extern void __libc_init_array(void); + +extern int main(int, char**, char**); + +extern void exit(int) __attribute__((noreturn, weak)); + +/* The linker must ensure that these are at least 4-byte aligned. */ +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +struct rom_img_cfg { + int *img_start; +}; + +extern char _lm_rom_img_cfgp; + +void __attribute__((noreturn)) start_c(void) { + struct rom_img_cfg *img_cfg = (struct rom_img_cfg*)&_lm_rom_img_cfgp; + int *src = img_cfg->img_start; + int *dst = (int*)&__data_start__; + int exit_code; + + /* Initialize .data, if necessary. */ + if (src != dst) { + int *end = (int*)&__data_end__; + while (dst < end) { + *dst++ = *src++; + } + } + + /* Zero .bss. */ + dst = (int*)&__bss_start__; + while (dst < (int*)&__bss_end__) { + *dst++ = 0; + } + + /* Run initializers. */ + __libc_init_array(); + + /* Jump to main. */ + exit_code = main(0, 0, 0); + if (exit) { + exit(exit_code); + } + + /* If exit is NULL, make sure we don't return. */ + for (;;) + continue; +} diff --git a/tools/linux/maple_upload b/tools/linux/maple_upload index e799f3a..50d2ae5 100755 --- a/tools/linux/maple_upload +++ b/tools/linux/maple_upload @@ -38,3 +38,12 @@ if [ ! -x "${DFU_UTIL}" ]; then fi "${DFU_UTIL}" -d ${usbID} -a ${altID} -D ${binfile} ${dfuse_addr} -R + +echo -n Waiting for ${dummy_port_fullpath} serial... + +COUNTER=0 +while [ ! -r ${dummy_port_fullpath} ] && ((COUNTER++ < 40)); do + sleep 0.1 +done + +echo Done diff --git a/tools/linux/serial_upload b/tools/linux/serial_upload index 05d17c6..755444a 100755 --- a/tools/linux/serial_upload +++ b/tools/linux/serial_upload @@ -1,2 +1,2 @@ #!/bin/bash -$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 230400 -w "$4" /dev/"$1" +$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" diff --git a/tools/linux64/install.sh b/tools/linux64/install.sh index 29ddb2f..9d4caad 100755 --- a/tools/linux64/install.sh +++ b/tools/linux64/install.sh @@ -17,7 +17,8 @@ if sudo [ -w /etc/udev/rules.d ]; then echo "Reloading udev rules" sudo udevadm control --reload-rules echo "Adding current user to dialout group" - sudo adduser $USER dialout + #sudo adduser $USER dialout + sudo usermod -aG dialout $USER else echo "Couldn't copy to /etc/udev/rules.d/; you probably have to run this script as root? Or your distribution of Linux doesn't include udev; try running the IDE itself as root." fi diff --git a/tools/linux64/maple_upload b/tools/linux64/maple_upload index e799f3a..27e006c 100755 --- a/tools/linux64/maple_upload +++ b/tools/linux64/maple_upload @@ -38,3 +38,12 @@ if [ ! -x "${DFU_UTIL}" ]; then fi "${DFU_UTIL}" -d ${usbID} -a ${altID} -D ${binfile} ${dfuse_addr} -R + +echo -n Waiting for ${dummy_port_fullpath} serial... + +COUNTER=0 +while [ ! -c ${dummy_port_fullpath} ] && ((COUNTER++ < 40)); do + sleep 0.1 +done + +echo Done \ No newline at end of file diff --git a/tools/linux64/serial_upload b/tools/linux64/serial_upload index 05d17c6..755444a 100755 --- a/tools/linux64/serial_upload +++ b/tools/linux64/serial_upload @@ -1,2 +1,2 @@ #!/bin/bash -$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 230400 -w "$4" /dev/"$1" +$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" diff --git a/tools/macosx/jlink_upload b/tools/macosx/jlink_upload new file mode 100755 index 0000000..a9e9810 --- /dev/null +++ b/tools/macosx/jlink_upload @@ -0,0 +1,9 @@ +#!/bin/bash + +echo erase > "$1".jlink +echo loadbin "$1" , 0x8000000 >> "$1".jlink +echo r >> "$1".jlink +echo q >> "$1".jlink + +/Applications/SEGGER/JLink/JLinkExe -device STM32F103C8 -if SWD -speed auto -CommanderScript "$1".jlink + diff --git a/tools/macosx/maple_upload b/tools/macosx/maple_upload index 8d15eff..3521aa1 100755 --- a/tools/macosx/maple_upload +++ b/tools/macosx/maple_upload @@ -51,3 +51,12 @@ if [ ! -x ${DFU_UTIL} ]; then fi ${DFU_UTIL} -d ${usbID} -a ${altID} -D ${binfile} -R ${dfuse_addr} -R + +echo -n Waiting for ${dummy_port_fullpath} serial... + +COUNTER=0 +while [ ! -c ${dummy_port_fullpath} ] && ((COUNTER++ < 40)); do + sleep 0.1 +done + +echo Done diff --git a/tools/macosx/serial_upload b/tools/macosx/serial_upload index 05d17c6..755444a 100755 --- a/tools/macosx/serial_upload +++ b/tools/macosx/serial_upload @@ -1,2 +1,2 @@ #!/bin/bash -$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 230400 -w "$4" /dev/"$1" +$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" diff --git a/tools/win/cygiconv-2.dll b/tools/win/cygiconv-2.dll deleted file mode 100644 index 64fd39e..0000000 Binary files a/tools/win/cygiconv-2.dll and /dev/null differ diff --git a/tools/win/cygwin1.dll b/tools/win/cygwin1.dll deleted file mode 100644 index 83e58ea..0000000 Binary files a/tools/win/cygwin1.dll and /dev/null differ diff --git a/tools/win/hid_flash/hid-flash.exe b/tools/win/hid_flash/hid-flash.exe new file mode 100644 index 0000000..9808b20 Binary files /dev/null and b/tools/win/hid_flash/hid-flash.exe differ diff --git a/tools/win/maple_upload.bat b/tools/win/maple_upload.bat index 678969c..7d59bf5 100644 --- a/tools/win/maple_upload.bat +++ b/tools/win/maple_upload.bat @@ -6,3 +6,13 @@ set driverLetter=%driverLetter:~0,2% %driverLetter% cd %~dp0 java -jar maple_loader.jar %1 %2 %3 %4 %5 %6 %7 %8 %9 + +for /l %%x in (1, 1, 40) do ( + ping -w 50 -n 1 192.0.2.1 > nul + mode %1 > nul + if ERRORLEVEL 0 goto comPortFound +) + +echo timeout waiting for %1 serial + +:comPortFound diff --git a/tools/win/serial_upload.bat b/tools/win/serial_upload.bat index d733be7..4c50fb7 100644 --- a/tools/win/serial_upload.bat +++ b/tools/win/serial_upload.bat @@ -8,7 +8,7 @@ cd %~dp0 rem: the two line below are needed to fix path issues with incorrect slashes before the bin file name set str=%4 set str=%str:/=\% -stm32flash -g 0x8000000 -b 230400 -w %str% %1 +stm32flash -g 0x8000000 -b 115200 -w %str% %1 rem: C:\Python27\python.exe stm32loader.py -e -w -p %1 -g -b 115200 %str% rem: ------------- use STM's own uploader