Compare commits

...

50 Commits

Author SHA1 Message Date
King Kévin d9a7430481 busvoodoo: minor, simplify license 2021-03-31 14:10:07 +02:00
King Kévin 967cbb1832 application: fix merge with master 2021-03-31 14:10:07 +02:00
King Kévin b11a0b85df application: fix merge 2021-03-31 14:10:07 +02:00
King Kévin f8c84294ad busvoodoo: re-add 1-Wire (enough space on genuine STM32) 2021-03-31 14:10:07 +02:00
King Kévin 0a1877fbbc busvoodoo_hiz: led LED blink for a bit longer 2021-03-31 14:10:07 +02:00
King Kévin 6e05f18d2b usb: don't include date in serial, so we can have a constant by id path 2021-03-31 14:10:07 +02:00
King Kévin 1b857110ce Rakefile: add target address when flashing using stm32flash 2021-03-31 14:10:07 +02:00
King Kévin 19447081fe usb_cdcacm: fix product string 2021-03-31 14:10:07 +02:00
King Kévin 5eee616a32 application: don't run firmware when still in stlink 2021-03-31 14:10:07 +02:00
King Kévin 96b33f5b0d busvoodoo_hiz: fix self test for dongle 2021-03-31 14:10:07 +02:00
King Kévin 7d8c5fbd72 busvoodoo_hiz: kick dog on user input + wait for disconnect 2021-03-31 14:10:07 +02:00
King Kévin db98878e63 busvoodoo_global: disable SWJ for dongle 2021-03-31 14:10:07 +02:00
King Kévin 4ca7fa65ec busvoodoo_hiz: fix family check for dongle 2021-03-31 14:10:07 +02:00
King Kévin 8fab76dc5d application: minor, put spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin 4194af4e10 busvoodoo_hiz: minor, replace printf with puts 2021-03-31 14:10:07 +02:00
King Kévin 7a874bdb77 busvoodoo_hiz: minor, put spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin ecfa216d48 busvoodoo_uart: minor, put spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin cbc37e3a45 busvoodoo_uart_generic: minor, replace printf with puts 2021-03-31 14:10:07 +02:00
King Kévin dfcdd512d1 busvoodoo_uart_generic: minor, put spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin d9ae0d0fa2 busvoodoo_onewire: minor, replace printf with puts 2021-03-31 14:10:07 +02:00
King Kévin b64845ef16 busvoodoo_onewire: minor, put spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin b81df746c6 busvoodoo_global: minor, replace printf with puts 2021-03-31 14:10:07 +02:00
King Kévin b8bce07b84 busvoodoo_global: define dongle IO pins 2021-03-31 14:10:07 +02:00
King Kévin 162cffc5d8 busvoodoo_global: fix dongle ADC voltage divider 2021-03-31 14:10:07 +02:00
King Kévin d0d6ba0e57 busvoodoo_global: minor, remove unsupported dongle feature 2021-03-31 14:10:07 +02:00
King Kévin b6d567462c busvoodoo_global: minor, add version voltage documentation 2021-03-31 14:10:07 +02:00
King Kévin f28bf07f78 busvoodoo_global: minor, add spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin 01aefc2e19 busvoodoo_spi: minor, use puts instead of printf 2021-03-31 14:10:07 +02:00
King Kévin d7fbc894aa busvoodoo_spi: minor, add spaces around operators 2021-03-31 14:10:07 +02:00
King Kévin 2351a1c221 application: remove features unsupported by dongle 2021-03-31 14:10:07 +02:00
King Kévin 92fd728774 application: simple welcome string (dongle compatible) 2021-03-31 14:10:07 +02:00
King Kévin 41d4350220 busvoodoo_onewire: remove features unsupported by dongle 2021-03-31 14:10:07 +02:00
King Kévin c35af16137 onewire_master: use pin also available on dongle 2021-03-31 14:10:07 +02:00
King Kévin 35ffb5586c busvoodoo_i2c: remove features unsupported by dongle 2021-03-31 14:10:07 +02:00
King Kévin e0f7f5c39c busvoodoo_spi: remove features unsupported by dongle 2021-03-31 14:10:07 +02:00
King Kévin f4231c9cc0 busvoodoo_uart: remove features unsupported by dongle 2021-03-31 14:10:07 +02:00
King Kévin 67b7243736 busvoodoo_hiz: remove features unsupported by dongle 2021-03-31 14:10:07 +02:00
King Kévin d911103ee7 busvoodoo_global: add definitions for dongle and remove unsupported features 2021-03-31 14:10:07 +02:00
King Kévin 2ed71d68e5 global: disable DEBUG to enable watchdog 2021-03-31 14:10:07 +02:00
King Kévin 83a6ad958f global: define DFI pin for dongle (even if it is not used) 2021-03-31 14:10:07 +02:00
King Kévin 90a1f3a98b Rakefile: add flashing over UART bootloader for dongle 2021-03-31 14:10:07 +02:00
King Kévin 4a70ed2ff7 Rakefile: add dongle definition and specific linker script 2021-03-31 14:10:07 +02:00
King Kévin 3475565ef4 Rakefile: add prepprocessor to dependency generator to take ifdef into consideration 2021-03-31 14:10:07 +02:00
King Kévin b5068114fc application: remove ifdef for other boards 2021-03-31 14:10:07 +02:00
King Kévin c5dfa4371e BV I2C: use i2c_master_slave_read and print_xxd in dump8 2021-03-31 14:10:07 +02:00
King Kévin a404e5ffc4 BV I2C: check dump8 input argument 2021-03-31 14:10:07 +02:00
King Kévin 7488ebd737 BV I2C: warn when reset failed 2021-03-31 14:10:07 +02:00
King Kévin 89e53cb378 (minor) remove trailing spaces 2021-03-31 14:10:07 +02:00
King Kévin 84fbd01d01 BV I2C: use new librarz and add dump8 command 2021-03-31 14:10:07 +02:00
King Kévin f76482db93 make busvoodoo branch follow master
making a rebase of the old busvoodoo branch against master would
cost to much time and would not be pretty.
instead I copied all existing busvoodoo file onto a new busvoodoo
branch of master.
this will allow to do a rebase on master in the future
all individual commits are now in the busvoodoo_premaster branch.
2021-03-31 14:10:07 +02:00
34 changed files with 7492 additions and 340 deletions

74
HACKING.md Normal file
View File

@ -0,0 +1,74 @@
The following information will focus on the software development.
board
=====
The BusVoodoo uses a [custom board](https://bus.cuvoodoo.info/manual/index.html#_hardware_development) based on a [STM32F103RC](http://www.st.com/en/microcontrollers/stm32f103rc.html) micro-controller.
code
====
dependencies
------------
To develop the firmware, following Linux packages are required:
- _arm-none-eabi-gcc_ to compile the source code
- _arm-none-eabi-binutils_ to create the firmware binaries
- _arm-none-eabi-gdb_ to debug the firmware
- _rake_ automate development steps
- _openocd_ to flash and debug over SWD (when using an ST-Link V2 adapter)
- _doxygen_ to compile the documentation
The source code uses the [libopencm3](http://libopencm3.org/) library.
The projects is already a git submodules.
It will be initialized when compiling the firmware.
Alternatively you can run once: `git submodule init` and `git submodule update`.
firmware
--------
To compile the firmware files run `rake`.
This will generate two firmware:
- _bootloader_: a USB DFU bootloader
- _application_: the main application
*IMPORTANT*: to build the firmware for BusVoodoo hardware version 0, prepend `BUSVOODOO_HARDWARE_VERSION=0` before every `rake` command. This will make sure the few pin assignment differences are taken into account in the firmware.
documentation
-------------
To generate doxygen documentation run `rake doc`.
The documentation describing all files, functions, and variables will be available in the _doc_ folder.
Further comments are in the source code.
flash
-----
There are two firmware images: `bootloader` and `application`.
The `bootloader` image allows to flash the `application` over USB using the DFU protocol.
The `bootloader` is started first and immediately jumps to the `application` if it is valid and the DFU mode is not forced.
The `application` image is the main application and is implemented in `application.c`.
The `bootloader` image will be flashed using SWD (Serial Wire Debug).
For that you need an SWD adapter.
The `Makefile` uses a Black Magic Probe (per default), or a ST-Link V2 along OpenOCD software.
To flash the `booltoader` using SWD run `rake flash_booloader`.
Once the `bootloader` is flashed it is possible to flash the `application` over USB using the DFU protocol by running `rake flash`.
The `application` advertises USB DFU support (along with the USB CDC ACM class).
If the application is broken, force the bootloader to start the DFU mode by shorting the contacts marked as DFU on the board while powering up.
It is also possible to flash the `application` image using SWD by running `rake flash_application`.
debug
-----
SWD also allows to debug the code running on the micro-controller using GDB.
To start the debugging session run `rake debug`.
USB
---
The firmware offers serial communication over USART 1 and USB (using the CDC ACM device class).

129
README.md
View File

@ -1,4 +1,4 @@
This firmware template is designed for development boards based around [STM32 F1 series micro-controller](http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1031).
This is the firmware for the [BusVoodoo](https://bus.cuvoodoo.info/).
project
=======
@ -6,98 +6,45 @@ project
summary
-------
*describe project purpose*
The BusVoodoo is a multi-protocol debugging adapter.
This tool allows to quickly communicate with various other electronic devices.
technology
----------
*described electronic details*
board
=====
The current implementation uses a [core board](https://wiki.cuvoodoo.info/doku.php?id=stm32f1xx#core_board).
The underlying template also supports following board:
- [Maple Mini](http://leaflabs.com/docs/hardware/maple-mini.html), based on a STM32F103CBT6
- [System Board](https://wiki.cuvoodoo.info/doku.php?id=stm32f1xx#system_board), based on a STM32F103C8T6
- [blue pill](https://wiki.cuvoodoo.info/doku.php?id=stm32f1xx#blue_pill), based on a STM32F103C8T6
- [black pill](https://wiki.cuvoodoo.info/doku.php?id=stm32f1xx#black_pill), based on a STM32F103C8T6
- [core board](https://wiki.cuvoodoo.info/doku.php?id=stm32f1xx#core_board), based on a STM32F103C8T6
- [ST-LINK V2 mini](https://wiki.cuvoodoo.info/doku.php?id=jtag#mini_st-link_v2), a ST-LINK/V2 clone based on a STM32F101C8T6
- [USB-Blaster](https://wiki.cuvoodoo.info/doku.php?id=jtag#armjishu_usb-blaster), an Altera USB-Blaster clone based on a STM32F101C8T6
**Which board is used is defined in the Makefile**.
This is required to map the user LED and button provided on the board
The ST-LINK V2 mini clone has SWD test points on the board.
Because read protection is enabled, you will first need to remove the protection to be able to flash the firmware.
To remove the read protection (and erase flash), run `rake remove_protection` while a SWD adapter is connected.
The Altera USB-Blaster clone has a pin header for SWD and UART1 on the board.
SWD is disabled in the main firmware, and it has read protection.
To be able to flash using SWD (or the serial port), the BOOT0 pin must be set to 1 to boot the system memory install of the flash memory.
To set BOOT0 to 1, apply 3.3 V on R11, between the resistor and the reference designator, when powering the device.
The red LED should stay off while the green LED is on.
Now you can remove the read protection (and erase flash), run `rake remove_protection` while a SWD adapter is connected.
connections
===========
Connect the peripherals the following way (STM32F10X signal; STM32F10X pin; peripheral pin; peripheral signal; comment):
- *list board to peripheral pin connections*
All pins are configured using `define`s in the corresponding source code.
code
====
dependencies
------------
The source code uses the [libopencm3](http://libopencm3.org/) library.
The projects is already a git submodules.
It will be initialized when compiling the firmware.
Alternatively you can run once: `git submodule init` and `git submodule update`.
firmware
--------
To compile the firmware run `rake`.
documentation
-------------
To generate doxygen documentation run `rake doc`.
flash
-----
There are two firmware images: `bootloader` and `application`.
The `bootloader` image allows to flash the `application` over USB using the DFU protocol.
The `bootloader` is started first and immediately jumps to the `application` if it is valid and the DFU mode is not forced (i.e. by pressing the user button on the board or requesting a DFU detach in the `application`).
The `application` image is the main application and is implemented in `application.c`.
It is up to the application to advertise USB DFU support (i.e. as does the provided USB CDC ACM example).
The `bootloader` image will be flashed using SWD (Serial Wire Debug).
For that you need an SWD adapter.
The `Makefile` uses a ST-Link V2 programmer along OpenOCD software (default), or Black Magic Probe.
To flash the `booltoader` using SWD run `rake flash_booloader`.
If the development board uses the CKS32 chip STM32 alternative, use `CPUTAPID=0x2ba01477 rake flash_booloader`.
Once the `bootloader` is flashed it is possible to flash the `application` over USB using the DFU protocol by running `rake flash`.
To force the bootloader to start the DFU mode press the user button or short a pin, depending on the board.
It is also possible to flash the `application` image using SWD by running `rake flash_application`.
debug
-----
SWD also allows to debug the code running on the micro-controller using GDB.
To start the debugging session run `rake debug`.
An overview of the BusVoodoo can be found [here](https://bus.cuvoodoo.info/)
A more detailed manual is available [here](https://bus.cuvoodoo.info/manual/).
USB
---
The firmware offers serial communication over USART1 and USB (using the CDC ACM device class).
The firmware offers serial communication over USART 1 and USB (using the CDC ACM device class).
board
=====
The BusVoodoo uses a [custom board](https://bus.cuvoodoo.info/manual/index.html#_hardware_development) based on an [STM32F103RC](http://www.st.com/en/microcontrollers/stm32f103rc.html) micro-controller.
firmware
========
binaries
--------
There are two firmware files:
- _bootloader_: a USB DFU bootloader
- _application_: the main application
flash
-----
How to flash the binary firmware files in described in the [manual](https://bus.cuvoodoo.info/manual/index.html#_flashing).
source
------
The source code is available in [git](https://git.cuvoodoo.info/busvoodoo_firmware/), under the **busvoodoo** branch (or **busvoodoo_v0** for hardware version 0).
This firmware also uses the [LibOpenCM3](http://libopencm3.org/) library.
development
-----------
For information about firmware development, check the _HACKING.md_ instructions.

View File

@ -15,7 +15,7 @@ FIRMWARES = [BOOTLOADER, APPLICATION]
# which development board is used
# supported are: SYSTEM_BOARD, MAPLE_MINI, BLUE_PILL, BLACK_PILL, CORE_BOARD, STLINKV2, BLASTER, BUSVOODOO
BOARD = ENV["BOARD"] || "BLUE_PILL"
BOARD = ENV["BOARD"] || "BUSVOODOO"
# libopencm3 definitions
LIBOPENCM3_DIR = "libopencm3"
@ -38,6 +38,10 @@ OBJCOPY = PREFIX+"-objcopy"
OBJDUMP = PREFIX+"-objdump"
GDB = PREFIX+"-gdb"
# BusVoodoo hardware version (0=0, 1=A, 2=DONGLE)
# mainly because version 0 uses different pins)
BUSVOODOO_HARDWARE_VERSION = ENV["BUSVOODOO_HARDWARE_VERSION"] || 1
# compiler flags
cflags = [ENV["CFLAGS"]]
# optimize for size
@ -144,17 +148,23 @@ end
desc "compile source into object"
rule '.o' => ['.c', proc{|f| File.file?(f.ext("h")) ? f.ext("h") : []}, proc{|f| dependencies(f).collect{|d| File.file?(d.ext("h")) ? d.ext("h") : []}}, "#{LIBOPENCM3_LIB}/lib#{STM32F1_LIB}.a"] do |t|
sh "#{CC} #{cflags} #{archflags} -o #{t.name} -c #{t.prerequisites[0]}"
sh "#{CC} #{cflags} #{archflags} -DBUSVOODOO_HARDWARE_VERSION='#{BUSVOODOO_HARDWARE_VERSION}' -o #{t.name} -c #{t.prerequisites[0]}"
end
desc "generate dependencies"
rule '.d' => ['.c', "#{LIBOPENCM3_LIB}/lib#{STM32F1_LIB}.a"] do |t|
sh "#{CC} #{cflags} #{archflags} -MM -MF #{t.name} -c #{t.prerequisites[0]}"
sh "#{CC} #{cflags} #{archflags} -DBUSVOODOO_HARDWARE_VERSION='#{BUSVOODOO_HARDWARE_VERSION}' -MM -MF #{t.name} -c #{t.prerequisites[0]}"
end
desc "link binary"
rule '.elf' => ['.o', proc{|f| dependencies(f)}, '.ld', "#{LIBOPENCM3_LIB}/lib#{STM32F1_LIB}.a"] do |t|
sh "#{LD} #{archflags} #{ldflags.join(' ')} #{t.prerequisites[0..-3].join(' ')} -T#{t.name.ext('ld')} #{ldflags_linker.collect{|flag| "-Wl,"+flag}.join(' ')} #{library_paths.collect{|path| "-L"+path}.join(' ')} #{ldlibs.collect{|lib| "-l"+lib}.join(' ')} -Wl,--start-group #{ldlibs_linker.collect{|lib| "-l"+lib}.join(' ')} -Wl,--end-group --output #{t.name}"
if "2" != BUSVOODOO_HARDWARE_VERSION then
rule '.elf' => ['.o', proc{|f| dependencies(f)}, '.ld', "#{LIBOPENCM3_LIB}/lib#{STM32F1_LIB}.a"] do |t|
sh "#{LD} #{archflags} #{ldflags.join(' ')} #{t.prerequisites[0..-3].join(' ')} -T#{t.name.ext('ld')} #{ldflags_linker.collect{|flag| "-Wl,"+flag}.join(' ')} #{library_paths.collect{|path| "-L"+path}.join(' ')} #{ldlibs.collect{|lib| "-l"+lib}.join(' ')} -Wl,--start-group #{ldlibs_linker.collect{|lib| "-l"+lib}.join(' ')} -Wl,--end-group --output #{t.name}"
end
else
rule '.elf' => ['.o', proc{|f| dependencies(f)}, '.dongle.ld', "#{LIBOPENCM3_LIB}/lib#{STM32F1_LIB}.a"] do |t|
sh "#{LD} #{archflags} #{ldflags.join(' ')} #{t.prerequisites[0..-3].join(' ')} -T#{t.name.ext('dongle.ld')} #{ldflags_linker.collect{|flag| "-Wl,"+flag}.join(' ')} #{library_paths.collect{|path| "-L"+path}.join(' ')} #{ldlibs.collect{|lib| "-l"+lib}.join(' ')} -Wl,--start-group #{ldlibs_linker.collect{|lib| "-l"+lib}.join(' ')} -Wl,--end-group --output #{t.name}"
end
end
desc "export binary"
@ -183,8 +193,12 @@ SRC_DIRS.each do |src_dir|
end
# SWD/JTAG adapter used
# supported are : STLINKV2 (ST-Link V2), BMP (Black Magic Probe)
SWD_ADAPTER = ENV["SWD_ADAPTER"] || "STLINKV2"
# supported are : STLINKV2 (ST-Link V2), BMP (Black Magic Probe), UART
if "2" != BUSVOODOO_HARDWARE_VERSION then
SWD_ADAPTER = ENV["SWD_ADAPTER"] || "STLINKV2"
else
SWD_ADAPTER = ENV["SWD_ADAPTER"] || "UART"
end
# openOCD path to control the adapter
OOCD = ENV["OOCD"] || "openocd"
# openOCD adapted name
@ -198,36 +212,42 @@ CPUTAPID = ENV["CPUTAPID"] || "0x1ba01477"
desc "flash application using USB DFU"
task :flash => APPLICATION+".bin" do |t|
sh "dfu-util --device 1209:4356 --download #{t.source}"
sh "dfu-util --device 1209:4256 --download #{t.source}"
end
desc "remove STM32F1 protection using SWD"
desc "remove STM32F1 protection using SWD/UART"
task :remove_protection do
case SWD_ADAPTER
when "STLINKV2"
sh "#{OOCD} --file interface/#{OOCD_INTERFACE}.cfg --command 'transport select hla_swd' --command 'set CPUTAPID #{CPUTAPID}' --file target/#{OOCD_TARGET}.cfg --command 'init' --command 'halt' --command 'reset init' --command 'stm32f1x unlock 0' --command 'reset init' --command 'flash protect 0 0 last off' --command 'reset init' --command 'stm32f1x options_write 0 SWWDG NORSTSTNDBY NORSTSTOP' --command 'reset init' --command 'stm32f1x mass_erase 0' --command 'shutdown'"
when "BMP"
sh "#{GDB} --eval-command='target extended-remote #{BMP_PORT}' --eval-command='set confirm off' --eval-command='monitor swdp_scan' --eval-command='attach 1' --eval-command='monitor option erase' --eval-command='monitor erase_mass' --eval-command='kill' --eval-command='quit'"
when "UART"
sh "stm32flash -k -R /dev/ttyUSB0"
end
end
desc "flash bootloader using SWD"
desc "flash bootloader using SWD/UART"
task :flash_bootloader => BOOTLOADER+".hex" do |t|
case SWD_ADAPTER
when "STLINKV2"
sh "#{OOCD} --file interface/#{OOCD_INTERFACE}.cfg --command 'transport select hla_swd' --command 'set CPUTAPID #{CPUTAPID}' --file target/#{OOCD_TARGET}.cfg --command 'init' --command 'halt' --command 'reset init' --command 'flash erase_sector 0 0 last' --command 'flash write_image erase #{t.source}' --command 'reset' --command 'shutdown'"
when "BMP"
sh "#{GDB} --eval-command='target extended-remote #{BMP_PORT}' --eval-command='set confirm off' --eval-command='monitor swdp_scan' --eval-command='attach 1' --eval-command='monitor erase_mass' --eval-command='load' --eval-command='kill' --eval-command='quit' #{t.source}"
when "UART"
sh "stm32flash -w #{t.source} -v /dev/ttyUSB0"
end
end
desc "flash application using SWD"
desc "flash application using SWD/UART"
task :flash_application => APPLICATION+".hex" do |t|
case SWD_ADAPTER
when "STLINKV2"
sh "#{OOCD} --file interface/#{OOCD_INTERFACE}.cfg --command 'transport select hla_swd' --command 'set CPUTAPID #{CPUTAPID}' --file target/#{OOCD_TARGET}.cfg --command 'adapter speed 100' --command 'init' --command 'halt' --command 'reset init' --command 'flash write_image erase #{t.source}' --command 'reset' --command 'shutdown'"
when "BMP"
sh "#{GDB} --eval-command='target extended-remote #{BMP_PORT}' --eval-command='set confirm off' --eval-command='monitor swdp_scan' --eval-command='attach 1' --eval-command='load' --eval-command='kill' --eval-command='quit' #{t.source}"
when "UART"
sh "stm32flash -S 0x08002000 -w #{t.source} -v /dev/ttyUSB0"
end
end
@ -240,6 +260,8 @@ task :debug => APPLICATION+".elf" do |t|
exec("#{GDB} --eval-command='target remote | #{OOCD} --file interface/#{OOCD_INTERFACE}.cfg --command \"transport select hla_swd\" --command \"set CPUTAPID #{CPUTAPID}\" --file target/#{OOCD_TARGET}.cfg --command \"gdb_port pipe; log_output /dev/null; init\"' #{t.source}")
when "BMP"
exec("#{GDB} --eval-command='target extended-remote #{BMP_PORT}' --eval-command='monitor version' --eval-command='monitor swdp_scan' --eval-command='attach 1' #{t.source}")
when "UART"
sh "stm32flash -w #{t.source} -v -R /dev/ttyUSB0"
end
end

View File

@ -1,4 +1,4 @@
/** STM32F1 application example
/** STM32F1 BusVoodoo application
* @file
* @author King Kévin <kingkevin@cuvoodoo.info>
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
@ -7,33 +7,35 @@
/* standard libraries */
#include <stdint.h> // standard integer types
#include <stdlib.h> // standard utilities
#include <string.h> // string utilities
#include <time.h> // date/time utilities
#include <ctype.h> // utilities to check chars
/* STM32 (including CM3) libraries */
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
#include <libopencm3/cm3/scb.h> // vector table definition
#include <libopencm3/cm3/nvic.h> // interrupt utilities
#include <libopencm3/stm32/gpio.h> // general purpose input output library
#include <libopencm3/stm32/rcc.h> // real-time control clock library
#include <libopencm3/stm32/exti.h> // external interrupt utilities
#include <libopencm3/stm32/dbgmcu.h> // debug utilities
#include <libopencm3/stm32/rtc.h> // real time clock utilities
#include <libopencm3/stm32/iwdg.h> // independent watchdog utilities
#include <libopencm3/stm32/dbgmcu.h> // debug utilities
#include <libopencm3/stm32/desig.h> // design utilities
#include <libopencm3/stm32/flash.h> // flash utilities
/* own libraries */
#include "global.h" // board definitions
#include "print.h" // printing utilities
#if !defined(STLINKV2)
#include "uart.h" // USART utilities
#endif
#include "usb_cdcacm.h" // USB CDC ACM utilities
#include "terminal.h" // handle the terminal interface
#include "menu.h" // menu utilities
#include "busvoodoo_global.h" // BusVoodoo definitions
#include "busvoodoo_hiz.h" // BusVoodoo HiZ mode
#include "busvoodoo_uart.h" // BusVoodoo UART mode
#include "busvoodoo_i2c.h" // BusVoodoo I2C mode
#include "busvoodoo_spi.h" // BusVoodoo SPI mode
#include "busvoodoo_onewire.h" // BusVoodoo 1-wire mode
#if BUSVOODOO_HARDWARE_VERSION != 2
#include "uart.h" // USART utilities
#include "busvoodoo_oled.h" // OLED utilities
#include "busvoodoo_rs232.h" // BusVoodoo RS-232 mode
#include "busvoodoo_rs485.h" // BusVoodoo RS-485/422 mode
#include "busvoodoo_sdio.h" // BusVoodoo SDIO mode
#endif
/** watchdog period in ms */
#define WATCHDOG_PERIOD 10000
@ -41,32 +43,31 @@
/** set to 0 if the RTC is reset when the board is powered on, only indicates the uptime
* set to 1 if VBAT can keep the RTC running when the board is unpowered, indicating the date and time
*/
#if defined(CORE_BOARD)
#define RTC_DATE_TIME 1
#else
#define RTC_DATE_TIME 0
#endif
/** number of RTC ticks per second
* @note use integer divider of oscillator to keep second precision
*/
#define RTC_TICKS_SECOND 4
#if defined(RTC_DATE_TIME) && RTC_DATE_TIME
/** the start time from which to RTC ticks count
* @note this allows the 32-bit value to reach further in time, particularly when there are several ticks per second
*/
const time_t rtc_offset = 1577833200; // We 1. Jan 00:00:00 CET 2020
/** all supported BusVoodoo modes */
static const struct busvoodoo_mode_t* busvoodoo_modes[] = {
&busvoodoo_hiz_mode,
&busvoodoo_uart_mode,
&busvoodoo_i2c_mode,
&busvoodoo_spi_mode,
&busvoodoo_onewire_mode,
#if BUSVOODOO_HARDWARE_VERSION != 2
&busvoodoo_rs232_mode,
&busvoodoo_rs485_mode,
&busvoodoo_sdio_mode,
#endif
};
/** RTC time when device is started */
static time_t time_start = 0;
/** @defgroup main_flags flag set in interrupts to be processed in main task
* @{
*/
static volatile bool rtc_internal_tick_flag = false; /**< flag set when internal RTC ticked */
/** @} */
/** current BusVoodoo mode */
static struct busvoodoo_mode_t const * busvoodoo_mode = NULL;
/** is mode setup complete */
static bool busvoodoo_mode_complete = false;
size_t putc(char c)
{
@ -74,14 +75,14 @@ size_t putc(char c)
static char last_c = 0; // to remember on which character we last sent
if ('\n' == c) { // send carriage return (CR) + line feed (LF) newline for each LF
if ('\r' != last_c) { // CR has not already been sent
#if !defined(STLINKV2)
#if BUSVOODOO_HARDWARE_VERSION != 2
uart_putchar_nonblocking('\r'); // send CR over USART
#endif
usb_cdcacm_putchar('\r'); // send CR over USB
length++; // remember we printed 1 character
}
}
#if !defined(STLINKV2)
#if BUSVOODOO_HARDWARE_VERSION != 2
uart_putchar_nonblocking(c); // send byte over USART
#endif
usb_cdcacm_putchar(c); // send byte over USB
@ -90,40 +91,82 @@ size_t putc(char c)
return length; // return number of characters printed
}
/** display available commands
/** switch BusVoddoo mode
* @param[in] mode mode to switch to
*/
static void switch_mode(const struct busvoodoo_mode_t* mode)
{
if (busvoodoo_mode) {
(*busvoodoo_mode->exit)(); // exit current mode
}
busvoodoo_leds_off(); // switch off LEDs
busvoodoo_safe_state(); // return to safe state
// reset pinout
for (uint8_t i = 0; i < LENGTH(busvoodoo_global_pinout_io); i++) {
busvoodoo_global_pinout_io[i] = NULL;
}
#if BUSVOODOO_HARDWARE_VERSION != 2
for (uint8_t i = 0; i < LENGTH(busvoodoo_global_pinout_rscan); i++) {
busvoodoo_global_pinout_rscan[i] = NULL;
}
busvoodoo_oled_clear(); // clear OLED display buffer
busvoodoo_oled_update(); // update OLED display
#endif
if (NULL == mode) { // no mode provided
busvoodoo_mode = &busvoodoo_hiz_mode; // use default mode
} else { // mode provided
busvoodoo_mode = mode; // set provided mode a current mode
}
busvoodoo_mode_complete = (*busvoodoo_mode->setup)(&terminal_prefix, NULL); // start setup
terminal_send(0); // update the terminal prompt
}
/** command to show help
* @param[in] argument no argument required
*/
static void command_help(void* argument);
/** show software and hardware version
/** command to select mode
* @param[in] argument mode to select
*/
static void command_mode(void* argument);
/** command to quit current BusVoodoo mode
* @param[in] argument no argument required
*/
static void command_version(void* argument);
/** show uptime
* @param[in] argument no argument required
*/
static void command_uptime(void* argument);
#if RTC_DATE_TIME
/** show date and time
* @param[in] argument date and time to set
*/
static void command_datetime(void* argument);
#endif
/** reset board
static void command_quit(void* argument);
/** command to reset board
* @param[in] argument no argument required
*/
static void command_reset(void* argument);
/** switch to DFU bootloader
/** command to reboot into bootloader
* @param[in] argument no argument required
*/
static void command_bootloader(void* argument);
/** list of all supported commands */
static const struct menu_command_t menu_commands[] = {
{
.shortcut = 'm',
.name = "mode",
.command_description = "select mode",
.argument = MENU_ARGUMENT_STRING,
.argument_description = "[mode]",
.command_handler = &command_mode,
},
{
.shortcut = 'q',
.name = "quit",
.command_description = "quit current mode",
.argument = MENU_ARGUMENT_NONE,
.argument_description = NULL,
.command_handler = &command_quit,
},
{
.shortcut = 'R',
.name = "reset",
.command_description = "reset board",
.argument = MENU_ARGUMENT_NONE,
.argument_description = NULL,
.command_handler = &command_reset,
},
{
.shortcut = 'h',
.name = "help",
@ -132,48 +175,6 @@ static const struct menu_command_t menu_commands[] = {
.argument_description = NULL,
.command_handler = &command_help,
},
{
.shortcut = 'v',
.name = "version",
.command_description = "show software and hardware version",
.argument = MENU_ARGUMENT_NONE,
.argument_description = NULL,
.command_handler = &command_version,
},
{
.shortcut = 'u',
.name = "uptime",
.command_description = "show uptime",
.argument = MENU_ARGUMENT_NONE,
.argument_description = NULL,
.command_handler = &command_uptime,
},
#if RTC_DATE_TIME
{
.shortcut = 'd',
.name = "date",
.command_description = "show/set date and time",
.argument = MENU_ARGUMENT_STRING,
.argument_description = "[YYYY-MM-DD HH:MM:SS]",
.command_handler = &command_datetime,
},
#endif
{
.shortcut = 'r',
.name = "reset",
.command_description = "reset board",
.argument = MENU_ARGUMENT_NONE,
.argument_description = NULL,
.command_handler = &command_reset,
},
{
.shortcut = 'b',
.name = "bootloader",
.command_description = "reboot into DFU bootloader",
.argument = MENU_ARGUMENT_NONE,
.argument_description = NULL,
.command_handler = &command_bootloader,
},
};
static void command_help(void* argument)
@ -181,56 +182,50 @@ static void command_help(void* argument)
(void)argument; // we won't use the argument
printf("available commands:\n");
menu_print_commands(menu_commands, LENGTH(menu_commands)); // print global commands
}
static void command_version(void* argument)
{
(void)argument; // we won't use the argument
printf("firmware date: %04u-%02u-%02u\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY); // show firmware build date
printf("device serial: %08x%08x%04x%04x\n", DESIG_UNIQUE_ID2, DESIG_UNIQUE_ID1, DESIG_UNIQUE_ID0 & 0xffff, DESIG_UNIQUE_ID0 >> 16); // not that the half-works are reversed in the first word
}
static void command_uptime(void* argument)
{
(void)argument; // we won't use the argument
const uint32_t uptime = (rtc_get_counter_val() - time_start) / RTC_TICKS_SECOND; // get time from internal RTC
printf("uptime: %u.%02u:%02u:%02u\n", uptime / (24 * 60 * 60), (uptime / (60 * 60)) % 24, (uptime / 60) % 60, uptime % 60);
}
#if RTC_DATE_TIME
static void command_datetime(void* argument)
{
char* datetime = (char*)argument; // argument is optional date time
if (NULL == argument) { // no date and time provided, just show the current day and time
const time_t time_rtc = rtc_get_counter_val() / RTC_TICKS_SECOND + rtc_offset; // get time from internal RTC
const struct tm* time_tm = localtime(&time_rtc); // convert time
const char* days[] = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}; // the days of the week
printf("date: %s %d-%02d-%02d %02d:%02d:%02d\n", days[time_tm->tm_wday], 1900 + time_tm->tm_year, 1 + time_tm->tm_mon, time_tm->tm_mday, time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec);
} else { // date and time provided, set it
const char* malformed = "date and time malformed, expecting YYYY-MM-DD HH:MM:SS\n";
struct tm time_tm; // to store the parsed date time
if (strlen(datetime) != (4 + 1 + 2 + 1 + 2) + 1 + (2 + 1 + 2 + 1 + 2)) { // verify date/time is long enough
printf(malformed);
return;
}
if (!(isdigit((int8_t)datetime[0]) && isdigit((int8_t)datetime[1]) && isdigit((int8_t)datetime[2]) && isdigit((int8_t)datetime[3]) && '-' == datetime[4] && isdigit((int8_t)datetime[5]) && isdigit((int8_t)datetime[6]) && '-' == datetime[7] && isdigit((int8_t)datetime[8]) && isdigit((int8_t)datetime[9]) && ' ' == datetime[10] && isdigit((int8_t)datetime[11]) && isdigit((int8_t)datetime[12]) && ':' == datetime[13] && isdigit((int8_t)datetime[14]) && isdigit((int8_t)datetime[15]) && ':' == datetime[16] && isdigit((int8_t)datetime[17]) && isdigit((int8_t)datetime[18]))) { // verify format (good enough to not fail parsing)
printf(malformed);
return;
}
time_tm.tm_year = strtol(&datetime[0], NULL, 10) - 1900; // parse year
time_tm.tm_mon = strtol(&datetime[5], NULL, 10) - 1; // parse month
time_tm.tm_mday = strtol(&datetime[8], NULL, 10); // parse day
time_tm.tm_hour = strtol(&datetime[11], NULL, 10); // parse hour
time_tm.tm_min = strtol(&datetime[14], NULL, 10); // parse minutes
time_tm.tm_sec = strtol(&datetime[17], NULL, 10); // parse seconds
time_t time_rtc = mktime(&time_tm); // get back seconds
time_rtc -= rtc_offset; // remove start offset
time_start = time_rtc * RTC_TICKS_SECOND + (rtc_get_counter_val() - time_start); // update uptime with current date
rtc_set_counter_val(time_rtc * RTC_TICKS_SECOND); // save date/time to internal RTC
printf("date and time saved: %d-%02d-%02d %02d:%02d:%02d\n", 1900 + time_tm.tm_year, 1 + time_tm.tm_mon, time_tm.tm_mday, time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec);
menu_print_commands(busvoodoo_global_commands, busvoodoo_global_commands_nb); // print BusVoodoo global commands
#if BUSVOODOO_HARDWARE_VERSION != 2
if (busvoodoo_full) {
menu_print_commands(busvoodoo_global_full_commands, busvoodoo_global_full_commands_nb); // print BusVoodoo global commands
}
#endif
if (!busvoodoo_mode->full_only || busvoodoo_full) {
menu_print_commands(busvoodoo_mode->commands, busvoodoo_mode->commands_nb); // print BusVoodoo mode commands
}
}
#endif
static void command_mode(void* argument)
{
if (NULL == argument || 0 == strlen(argument)) { // no mode provided: list all modes
printf("available modes:\n");
for (uint8_t i = 0; i < LENGTH(busvoodoo_modes); i++) { // go through all modes
if (!busvoodoo_modes[i]->full_only || busvoodoo_full) {
printf("%s\t%s\n", busvoodoo_modes[i]->name, busvoodoo_modes[i]->description); // display mode information
}
}
} else { // mode provided
bool mode_found = false; // to know if we found the matching mode
for (uint8_t i = 0; i < LENGTH(busvoodoo_modes); i++) { // go through all modes
if (0 == strcmp(argument, busvoodoo_modes[i]->name)) { // check for corresponding mode
if (!busvoodoo_mode->full_only || busvoodoo_full) {
switch_mode(busvoodoo_modes[i]); // switch to mode
} else {
printf("mode only available for BusVoodoo full\n");
}
mode_found = true; // remember we found the mode
break; // stop searching for mode
}
}
if (!mode_found) {
printf("unknown mode: %s\n", argument);
}
}
}
static void command_quit(void* argument)
{
(void)argument; // we won't use the argument
switch_mode(NULL); // switch do default mode
}
static void command_reset(void* argument)
{
@ -239,18 +234,6 @@ static void command_reset(void* argument)
while (true); // wait for the reset to happen
}
static void command_bootloader(void* argument)
{
(void)argument; // we won't use the argument
// set DFU magic to specific RAM location
__dfu_magic[0] = 'D';
__dfu_magic[1] = 'F';
__dfu_magic[2] = 'U';
__dfu_magic[3] = '!';
scb_reset_system(); // reset system (core and peripherals)
while (true); // wait for the reset to happen
}
/** process user command
* @param[in] str user command string (\0 ended)
*/
@ -260,16 +243,36 @@ static void process_command(char* str)
if (NULL == menu_commands || 0 == LENGTH(menu_commands)) {
return;
}
// don't handle empty lines
if (!str || 0 == strlen(str)) {
return;
// handle user input
if (NULL == busvoodoo_mode) { // no mode set
switch_mode(NULL); // set default mode
}
bool command_handled = false;
if (!command_handled) {
command_handled = menu_handle_command(str, menu_commands, LENGTH(menu_commands)); // try if this is not a global command
}
if (!command_handled) {
printf("command not recognized. enter help to list commands\n");
if (!busvoodoo_mode_complete) { // mode setup is not complete
busvoodoo_mode_complete = (*busvoodoo_mode->setup)(&terminal_prefix, str); // continue setup
terminal_send(0); // update the terminal prompt
} else { // mode setup is complete
// don't handle empty lines
if (!str || 0 == strlen(str)) {
return;
}
bool command_handled = false;
if (!busvoodoo_mode->full_only || busvoodoo_full) {
command_handled = menu_handle_command(str, busvoodoo_mode->commands, busvoodoo_mode->commands_nb); // try if the mode can handle this command
}
#if BUSVOODOO_HARDWARE_VERSION != 2
if (!command_handled && busvoodoo_full) {
command_handled = menu_handle_command(str, busvoodoo_global_full_commands, busvoodoo_global_full_commands_nb); // try if full BusVoodoo can handle this command
}
#endif
if (!command_handled) {
command_handled = menu_handle_command(str, busvoodoo_global_commands, busvoodoo_global_commands_nb); // try if the base BusVoodoo can handle this command
}
if (!command_handled) {
command_handled = menu_handle_command(str, menu_commands, LENGTH(menu_commands)); // try if this is not a global command
}
if (!command_handled) {
printf("command not recognized. enter help to list commands\n");
}
}
}
@ -294,12 +297,14 @@ void main(void)
iwdg_start(); // start independent watchdog
#endif
// setup board
board_setup(); // setup board
#if !defined(STLINKV2)
#if BUSVOODOO_HARDWARE_VERSION != 2
uart_setup(); // setup USART (for printing)
#endif
busvoodoo_setup(); // setup BusVoodoo board
usb_cdcacm_setup(); // setup USB CDC ACM (for printing)
puts("\nwelcome to the CuVoodoo STM32F1 example application\n"); // print welcome message
puts("\nwelcome to \x1b[32mBus\x1b[35mVoodoo\x1b[0m\n"); // print welcome message
#if DEBUG
// show reset cause
@ -327,59 +332,70 @@ void main(void)
RCC_CSR |= RCC_CSR_RMVF; // clear reset flags
}
#endif
#if !(DEBUG)
// show watchdog information
printf("setup watchdog: %.2fs", WATCHDOG_PERIOD / 1000.0);
if (FLASH_OBR & FLASH_OBR_OPTERR) {
puts(" (option bytes not set in flash: software wachtdog used, not automatically started at reset)\n");
} else if (FLASH_OBR & FLASH_OBR_WDG_SW) {
puts(" (software watchdog used, not automatically started at reset)\n");
} else {
puts(" (hardware watchdog used, automatically started at reset)\n");
#if BUSVOODOO_HARDWARE_VERSION == 2
// on the STLINK/V2 PB7 is pulled high, while on the BusVoodoo dongle it is floating
#define BUSVOODOO_STLINK_PIN PB7
gpio_clear(GPIO_PORT(BUSVOODOO_STLINK_PIN), GPIO_PIN(BUSVOODOO_STLINK_PIN));
gpio_set_mode(GPIO_PORT(BUSVOODOO_STLINK_PIN), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_PIN(BUSVOODOO_STLINK_PIN));
sleep_ms(100); // wait for voltage to settle
if (gpio_get(GPIO_PORT(BUSVOODOO_STLINK_PIN), GPIO_PIN(BUSVOODOO_STLINK_PIN))) {
while (true) {
puts("solder the micro-controller on a BusVoodoo dongle\n");
iwdg_reset(); // kick the dog
sleep_ms(1000);
}
}
#endif
// setup RTC
puts("setup internal RTC: ");
#if defined(BLUE_PILL) || defined(STLINKV2) || defined(BLASTER) // for boards without a Low Speed External oscillator
// note: the blue pill LSE oscillator is affected when toggling the onboard LED, thus prefer the HSE
rtc_auto_awake(RCC_HSE, 8000000 / 128 / RTC_TICKS_SECOND - 1); // use High Speed External oscillator (8 MHz / 128) as RTC clock (VBAT can't be used to keep the RTC running)
#else // for boards with an precise Low Speed External oscillator
rtc_auto_awake(RCC_LSE, 32768 / RTC_TICKS_SECOND - 1); // ensure internal RTC is on, uses the 32.678 kHz LSE, and the prescale is set to our tick speed, else update backup registers accordingly (power off the micro-controller for the change to take effect)
#endif
rtc_interrupt_enable(RTC_SEC); // enable RTC interrupt on "seconds"
nvic_enable_irq(NVIC_RTC_IRQ); // allow the RTC to interrupt
time_start = rtc_get_counter_val(); // get start time from internal RTC
puts("OK\n");
// setup terminal
terminal_prefix = ""; // set default prefix
terminal_prefix = "BV"; // set default prefix
terminal_process = &process_command; // set central function to process commands
terminal_setup(); // start terminal
// start main loop
#if BUSVOODOO_HARDWARE_VERSION != 2
// setup OLED display
sleep_ms(10); // wait a bit until the display is ready
busvoodoo_oled_setup(); // setup OLED display
// display version
busvoodoo_oled_clear();
busvoodoo_oled_text_left("BusVoodoo");
char str[20];
snprintf(str, sizeof(str), "fl: %s", busvoodoo_full ? "full" : "light");
busvoodoo_oled_text_pos(1, 16+(fonts[FONT_KING10].height+2)*1, FONT_KING10, str);
snprintf(str, sizeof(str), "hw: %c", busvoodoo_version);
busvoodoo_oled_text_pos(1, 16+(fonts[FONT_KING10].height+2)*2, FONT_KING10, str);
snprintf(str, sizeof(str), "fw: %04u-%02u-%02u\n", BUILD_YEAR, BUILD_MONTH, BUILD_DAY);
busvoodoo_oled_text_pos(1, 16+(fonts[FONT_KING10].height+2)*3, FONT_KING10, str);
snprintf(str, sizeof(str), "bus.cuvoodoo.info");
busvoodoo_oled_text_pos((127-((fonts[FONT_KING8].width+1)*strlen(str)))/2, 63, FONT_KING8, str);
busvoodoo_oled_update();
sleep_ms(1000);
busvoodoo_oled_clear();
#endif
// setup default mode
switch_mode(NULL);
// main loop
bool action = false; // if an action has been performed don't go to sleep
button_flag = false; // reset button flag
while (true) { // infinite loop
iwdg_reset(); // kick the dog
if (user_input_available) { // user input is available
while (user_input_available) { // user input received
action = true; // action has been performed
led_toggle(); // toggle LED
char c = user_input_get(); // store receive character
terminal_send(c); // send received character to terminal
}
if (button_flag) { // user pressed button
action = true; // action has been performed
puts("button pressed\n");
led_toggle(); // toggle LED
sleep_ms(100); // wait a bit to remove noise and double trigger
button_flag = false; // reset flag
}
if (rtc_internal_tick_flag) { // the internal RTC ticked
rtc_internal_tick_flag = false; // reset flag
action = true; // action has been performed
if (0 == (rtc_get_counter_val() % RTC_TICKS_SECOND)) { // one second has passed
led_toggle(); // toggle LED (good to indicate if main function is stuck)
char c = user_input_get(); // get user input
if (0x04 == c) { // CTRL+D is used to quit the mode
printf("quit\n"); // acknowledge quitting
command_quit(NULL); // quit current mode
} else {
terminal_send(c); // send received character to terminal
}
}
if (action) { // go to sleep if nothing had to be done, else recheck for activity
@ -394,5 +410,4 @@ void main(void)
void rtc_isr(void)
{
rtc_clear_flag(RTC_SEC); // clear flag
rtc_internal_tick_flag = true; // notify to show new time
}

30
application.dongle.ld Normal file
View File

@ -0,0 +1,30 @@
/* linker script for application running on STM32F103x8 micro-controller
* the STM32F103x8 has 64 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* the STM32F103xB has 128 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* STM32F103x8 most often have in fact 128 KB, instead of the specified and advertised 64 KB, like the STM32F103xB
* CS32F103x8 has really only 64 KB of flash, which is not enough for he BusVoodoo firmware
* the USB DFU bootloader will take the first 8 KB of flash, followed by the application
* the first 4 bytes of the RAM is reserved for the DFU magic word (DFU! to start DFU bootloader)
*/
/* define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000 + 8K, LENGTH = 128K - 8K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 20K - 4
}
PROVIDE(__application_beginning = ORIGIN(rom));
/* if you want the firmware to use the flash size advertised by the micro-controller itself, use the following:
PROVIDE(__application_end = 0);
PROVIDE(__flash_end = 0);
if you want to enforce a flash size, because there is more flash than advertized by the micro-controller, use to following:
PROVIDE(__application_end = ORIGIN(rom) + LENGTH(rom));
PROVIDE(__flash_end = ORIGIN(rom) + LENGTH(rom));
*/
PROVIDE(__application_end = ORIGIN(rom) + LENGTH(rom));
PROVIDE(__flash_end = ORIGIN(rom) + LENGTH(rom));
/* RAM location reserved so application can talk to bootloader and tell to start DFU */
PROVIDE(__dfu_magic = ORIGIN(ram) - 4);
/* include rest of the definitions for the ARM Cortex-M, including STM32F1 family */
INCLUDE cortex-m-generic.ld

View File

@ -1,8 +1,5 @@
/* linker script for application running on STM32F103x8 micro-controller
* the STM32F103x8 has 64 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* the STM32F103xB has 128 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* STM32F103x8 most often have if fact 128 KB, instead of the specified and advertised 64 KB, like the STM32F103xB
* you can define the desired flash size here.
* the STM32F103xC has 256 KB of flash starting at 0x0800 0000, and 48 KB of SRAM starting at 0x2000 0000 (exception for STM32F103RC in WLCSP64 package: 64 KB of SRAM)
* the USB DFU bootloader will take the first 8 KB of flash, followed by the application
* the first 4 bytes of the RAM is reserved for the DFU magic word (DFU! to start DFU bootloader)
*/
@ -10,16 +7,17 @@
/* define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000 + 8K, LENGTH = 64K - 8K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 20K - 4
rom (rx) : ORIGIN = 0x08000000 + 8K, LENGTH = 256K - 8K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 48K - 4
}
PROVIDE(__application_beginning = ORIGIN(rom));
/* if you want the firmware to use the flash size advertised by the micro-controller itself, use the following:
/* only provide application_end and/or flash_end if you want to force a flash size
i.e. STM32F103xC most often have if fact 512 KB instead of the specified and advertised 256 KB
PROVIDE(__application_end = __application_beginning + 512K - 8K);
PROVIDE(__flash_end = __application_beginning + 512K - 8K);
else
PROVIDE(__application_end = 0);
PROVIDE(__flash_end = 0);
if you want to enforce a flash size, because there is more flash than advertized by the micro-controller, use to following:
PROVIDE(__application_end = ORIGIN(rom) + LENGTH(rom));
PROVIDE(__flash_end = ORIGIN(rom) + LENGTH(rom));
*/
PROVIDE(__application_end = 0);
PROVIDE(__flash_end = 0);

30
bootloader.dongle.ld Normal file
View File

@ -0,0 +1,30 @@
/* linker script for application running on STM32F103x8 micro-controller
* the STM32F103x8 has 64 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* the STM32F103xB has 128 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* STM32F103x8 most often have in fact 128 KB, instead of the specified and advertised 64 KB, like the STM32F103xB
* CS32F103x8 has really only 64 KB of flash, which is not enough for he BusVoodoo firmware
* the USB DFU bootloader will take the first 8 KB of flash, followed by the application
* the first 4 bytes of the RAM is reserved for the DFU magic word (DFU! to start DFU bootloader)
*/
/* define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 20K - 4
}
PROVIDE(__application_beginning = ORIGIN(rom) + LENGTH(rom));
/* if you want the firmware to use the flash size advertised by the micro-controller itself, use the following:
PROVIDE(__application_end = 0);
PROVIDE(__flash_end = 0);
if you want to enforce a flash size, because there is more flash than advertised by the micro-controller, use to following:
PROVIDE(__application_end = ORIGIN(rom) + 128K);
PROVIDE(__flash_end = ORIGIN(rom) + 128K);
*/
PROVIDE(__application_end = ORIGIN(rom) + 128K);
PROVIDE(__flash_end = ORIGIN(rom) + 128K);
/* RAM location reserved so application can talk to bootloader and tell to start DFU */
PROVIDE(__dfu_magic = ORIGIN(ram) - 4);
/* include rest of the definitions for the ARM Cortex-M, including STM32F1 family */
INCLUDE cortex-m-generic.ld

View File

@ -1,8 +1,5 @@
/* linker script for application running on STM32F103x8 micro-controller
* the STM32F103x8 has 64 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* the STM32F103xB has 128 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* STM32F103x8 most often have if fact 128 KB, instead of the specified and advertised 64 KB, like the STM32F103xB
* you can define the desired flash size here.
/* linker script for application running on STM32F103xC micro-controller
* the STM32F103xC has 256 KB of flash starting at 0x0800 0000, and 48 KB of SRAM starting at 0x2000 0000
* the USB DFU bootloader will take the first 8 KB of flash, followed by the application
* the first 4 bytes of the RAM is reserved for the DFU magic word (DFU! to start DFU bootloader)
*/
@ -11,15 +8,16 @@
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 20K - 4
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 48K - 4
}
PROVIDE(__application_beginning = ORIGIN(rom) + LENGTH(rom));
/* if you want the firmware to use the flash size advertised by the micro-controller itself, use the following:
/* only provide application_end and/or flash_end if you want to force a flash size
i.e. STM32F103xC most often have if fact 512 KB instead of the specified and advertised 256 KB
PROVIDE(__application_end = __application_beginning + 512K - 8K);
PROVIDE(__flash_end = __application_beginning + 512K - 8K);
else
PROVIDE(__application_end = 0);
PROVIDE(__flash_end = 0);
if you want to enforce a flash size, because there is more flash than advertized by the micro-controller, use to following:
PROVIDE(__application_end = ORIGIN(rom) + LENGTH(rom));
PROVIDE(__flash_end = ORIGIN(rom) + LENGTH(rom));
*/
PROVIDE(__application_end = 0);
PROVIDE(__flash_end = 0);

View File

@ -7,7 +7,7 @@
#pragma once
/** enable debugging functionalities */
#define DEBUG true
#define DEBUG false
/** get the length of an array */
#define LENGTH(x) (sizeof(x) / sizeof((x)[0]))
@ -693,14 +693,15 @@ int32_t adds32_safe(int32_t a, int32_t b);
#define DFU_FORCE_PIN PA8 /**< GPIO pin (pin PA8, not SWD and UART pin on debug port) */
#define DFU_FORCE_VALUE 0 /**< short to nearby ground connection to force DFU */
#elif defined(BUSVOODOO)
#if BUSVOODOO_HARDWARE_VERSION==0
/* on BusVoodoo v0 DFU input is on PC7 */
#define DFU_FORCE_PIN PC7 /**< GPIO pin (pin PC7) */
#if BUSVOODOO_HARDWARE_VERSION == 0
#define DFU_FORCE_PIN PC7 /**< DFU is on pin PC7 */
#define DFU_FORCE_VALUE 1 /**< pin is pulled low, and goes high when shorted with VUSB */
#else
/* on BusVoodoo vA DFU input is on PC4 */
#define DFU_FORCE_PIN PC4 /**< GPIO pin (pin PC4) */
#elif BUSVOODOO_HARDWARE_VERSION == 1
#define DFU_FORCE_PIN PC4 /**< DFU is on pin PC4 */
#define DFU_FORCE_VALUE 1 /**< pin floating, set high when shorted with nearby VCC */
#elif BUSVOODOO_HARDWARE_VERSION == 2
#define DFU_FORCE_PIN PB9 /**< DFU is on pin PB9 */
#define DFU_FORCE_VALUE 1 /**< pin floating, set high when shorted with nearby 3V3 ( */
#endif
#else
#define DFU_FORCE_PIN PB2 /**< BOOT1 pin */

1025
lib/busvoodoo_global.c Normal file

File diff suppressed because it is too large Load Diff

261
lib/busvoodoo_global.h Normal file
View File

@ -0,0 +1,261 @@
/** BusVoodoo global definitions and methods
* @file
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2018-2020
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
* @note peripherals used: time @ref busvoodoo_led_timer
*/
#pragma once
#include "menu.h"
#if BUSVOODOO_HARDWARE_VERSION != 2
/** @defgroup busvoodoo_voltages pin to control voltage regulators and pull-ups definitions
* @{
*/
#define BUSVOODOO_5VPULLUP_PORT B /**< 5V pull-up enable pin (active low) */
#define BUSVOODOO_5VPULLUP_PIN 4 /**< 5V pull-up enable pin (active low) */
#define BUSVOODOO_OEPULLUP_PORT A /**< bus switch output enable pin to enable embedded pull-ups (active low) */
#define BUSVOODOO_OEPULLUP_PIN 15 /**< bus switch output enable pin to enable embedded pull-ups (active low) */
#define BUSVOODOO_LVEN_PORT A /**< low voltage (LV) enable pin (active high) */
#define BUSVOODOO_LVEN_PIN 6 /**< low voltage (LV) enable pin (active high) */
#define BUSVOODOO_HVEN_PORT A /**< high voltage (HV) enable pin (active low) */
#define BUSVOODOO_HVEN_PIN 7 /**< high voltage (HV) enable pin (active low) */
#define BUSVOODOO_VOUTEN_PORT B /**< voltage output (5V and 3.3V) enable pin (active low) */
#define BUSVOODOO_VOUTEN_PIN 3 /**< voltage output (5V and 3.3V) enable pin (active low) */
/** @} */
/** @defgroup busvoodoo_adc ADC inputs to measure voltages from voltage regulators
* @{
*/
#define BUSVOODOO_3V3_CHANNEL 12 /**< ADC channel to measure 3.3VV rail */
#define BUSVOODOO_5V_CHANNEL 9 /**< ADC channel to measure 5V rail */
#define BUSVOODOO_LV_CHANNEL 11 /**< ADC channel to measure LV rail */
#define BUSVOODOO_HV_CHANNEL 15 /**< ADC channel to measure HV rail */
/** @} */
/** @defgroup busvoodoo_dac DAC output to set voltages of voltage regulators
* @{
*/
#define BUSVOODOO_LVCTL_PORT A /**< pin to control LV output voltage */
#define BUSVOODOO_LVCTL_PIN 4 /**< pin to control LV output voltage */
#define BUSVOODOO_LVCTL_CHANNEL CHANNEL_1 /**< DAC channel to control LV output voltage */
#define BUSVOODOO_LV_SET(x) ((0.8*(1+30.0/10.0)-x)*(10.0/30.0)+0.8) /**< voltage to output for the DAC to set the desired LV output voltage (based on resistor values on the LV adjust pins and LV voltage reference) */
#define BUSVOODOO_HVCTL_PORT A /**< pin to control HV output voltage */
#define BUSVOODOO_HVCTL_PIN 5 /**< pin to control HV output voltage */
#define BUSVOODOO_HVCTL_CHANNEL CHANNEL_2 /**< DAC channel to control HV output voltage */
#define BUSVOODOO_HV_SET(x) ((1.25*(1+100.0/10.0)-x)*(10.0/100.0)+1.25) /**< voltage to output for the DAC to set the desired HV output voltage (based on resistor values on the HV adjust pins and HV voltage reference) */
/** @} */
/** @defgroup busvoodoo_rs232 RS-232 transceiver connection definition
* @{
*/
#define BUSVOODOO_RS232_EN_PORT B /**< RS-232 pin to enable receiver (active low, pulled up) */
#define BUSVOODOO_RS232_EN_PIN 5 /**< RS-232 pin to enable receiver (active low, pulled up) */
#define BUSVOODOO_RS232_SHDN_PORT C /**< RS-232 pin to enable transmitter (active high, pulled low) */
#define BUSVOODOO_RS232_SHDN_PIN 15 /**< RS-232 pin to enable transmitter (active high, pulled low) */
#define BUSVOODOO_RS232_RTS_PORT A /**< RS-232 Request-To-Send output pin */
#define BUSVOODOO_RS232_RTS_PIN 1 /**< RS-232 Request-To-Send output pin */
#define BUSVOODOO_RS232_CTS_PORT A /**< RS-232 Clear-To-Send input pin */
#define BUSVOODOO_RS232_CTS_PIN 0 /**< RS-232 Clear-To-Send input pin */
#define BUSVOODOO_RS232_TX_PORT A /**< RS-232 Transmit output pin */
#define BUSVOODOO_RS232_TX_PIN 2 /**< RS-232 Transmit output pin */
#define BUSVOODOO_RS232_RX_PORT A /**< RS-232 Receive input pin */
#define BUSVOODOO_RS232_RX_PIN 3 /**< RS-232 Receive input pin */
/** @} */
/** @defgroup busvoodoo_rs485 RS-485 (and RS-422) transceiver connection definition
* @{
*/
#define BUSVOODOO_RS485_RE_PORT C /**< RS-485 pin to enable receiver (active low, pulled up) */
#define BUSVOODOO_RS485_RE_PIN 13 /**< RS-485 pin to enable receiver (active low, pulled up) */
#define BUSVOODOO_RS485_DE_PORT C /**< RS-485 pin to enable transmitter (active high, pulled low) */
#define BUSVOODOO_RS485_DE_PIN 14 /**< RS-485 pin to enable transmitter (active high, pulled low) */
#define BUSVOODOO_RS485_TX_PORT A /**< RS-485 Transmit output pin */
#define BUSVOODOO_RS485_TX_PIN 2 /**< RS-485 Transmit output pin */
#define BUSVOODOO_RS485_RX_PORT A /**< RS-485 Receive input pin */
#define BUSVOODOO_RS485_RX_PIN 3 /**< RS-485 Receive input pin */
/** @} */
#if BUSVOODOO_HARDWARE_VERSION != 0
/** @defgroup busvoodoo_can CAN transceiver connection definition
* @{
*/
#define BUSVOODOO_CAN_EN_PORT C /**< signal to power CAN transceiver (active low, pulled high) */
#define BUSVOODOO_CAN_EN_PIN 7 /**< signal to power CAN transceiver (active low, pulled high) */
#define BUSVOODOO_CAN_TX_PORT B /**< CAN Transmit output pin */
#define BUSVOODOO_CAN_TX_PIN 9 /**< CAN Transmit output pin */
#define BUSVOODOO_CAN_RX_PORT B /**< CAN Receive input pin */
#define BUSVOODOO_CAN_RX_PIN 8 /**< CAN Receive input pin */
/** @} */
#endif // BUSVOODOO_HARDWARE_VERSION != 0
#else // BUSVOODOO_HARDWARE_VERSION != 2
/** pin to directly pull up I²C lines (resistors are optional) */
#define BUSVOODOO_I2C_PULLUP_PIN PA15
/** @defgroup busvoodoo_adc ADC inputs to measure voltages
* @{
*/
#define BUSVOODOO_ADC_CHANNEL 9 /**< ADC channel to measure ADC input */
/** @} */
#endif // BUSVOODOO_HARDWARE_VERSION != 2
/** @defgroup busvoodoo_version ADC pin used to identify hardware version based on voltage
*/
#define BUSVOODOO_HW_VERSION_PORT B /**< pin to identify hardware version */
#define BUSVOODOO_HW_VERSION_PIN 0 /**< pin to identify hardware version */
#define BUSVOODOO_HW_VERSION_CHANNEL 8 /**< ADC to identify hardware version */
/** @} */
/** recommended duration in ms for pulsing LEDs to show activity */
#define BUSVOODOO_LED_PULSE 100
/** printing text style */
enum busvoodoo_text_style_t {
BUSVOODOO_TEXT_STYLE_RESET, /**< remove text style */
BUSVOODOO_TEXT_STYLE_ERROR, /**< text style for errors (red) */
BUSVOODOO_TEXT_STYLE_WARNING, /**< text style for warnings (yellow) */
BUSVOODOO_TEXT_STYLE_INFO, /**< text style for information (green) */
};
/** BusVoodoo mode interface */
struct busvoodoo_mode_t {
const char* name; /**< name of the mode (i.e. protocol shortcut for the menu) */
const char* description; /**< human readable description of the mode (i.e. full protocol name) */
const bool full_only; /**< if this mode is available only for BusVoodoo full flavor */
bool (*setup)(char** prefix, const char* line); /**< function to setup mode (menu prefix can be used to ask parameter, and line will be the user provided response)*/
const struct menu_command_t* commands; /**< list of menu commands provided by mode */
const uint8_t commands_nb; /**< number of menu commands provided by mode */
void (*exit)(void); /**< function to exit from mode (i.e. releasing the peripheral) */
};
/** @defgroup busvoodoo_io I/O connector pin definition
* @{
*/
#if BUSVOODOO_HARDWARE_VERSION != 2
extern const char* busvoodoo_io_names[13]; /**< I/O individual signal names */
extern const uint32_t busvoodoo_io_ports[13]; /**< port of individual signals */
extern const uint32_t busvoodoo_io_pins[13]; /**< pin of individual signals */
extern const uint8_t busvoodoo_io_groups[13]; /**< which I/O pin (group) does the signal belong to */
#else
extern const char* busvoodoo_io_names[8]; /**< I/O individual signal names */
extern const uint32_t busvoodoo_io_ports[8]; /**< port of individual signals */
extern const uint32_t busvoodoo_io_pins[8]; /**< pin of individual signals */
extern const uint8_t busvoodoo_io_groups[8]; /**< which I/O pin (group) does the signal belong to */
#endif
/** @} */
/** is the BusVoodoo board fully populated (with HV voltage regulator, RS-232, RS-485, CAN transceiver on the back side) */
extern bool busvoodoo_full;
/** version of the hardware board */
extern char busvoodoo_version;
/** list of supported commands for base BusVoodoo */
extern const struct menu_command_t busvoodoo_global_commands[];
/** number supported commands for base BusVoodoo */
extern const uint8_t busvoodoo_global_commands_nb;
#if BUSVOODOO_HARDWARE_VERSION != 2
/** list of supported commands for BusVoodoo full only */
extern const struct menu_command_t busvoodoo_global_full_commands[];
/** number supported commands for BusVoodoo full only */
extern const uint8_t busvoodoo_global_full_commands_nb;
#endif
/** I/O connector pinout */
extern const char* busvoodoo_global_pinout_io[10];
#if BUSVOODOO_HARDWARE_VERSION != 2
/** RS/CAN connector pinout */
extern const char* busvoodoo_global_pinout_rscan[5];
#endif
/** shared string buffer, i.e. used when configuring modes */
extern char busvoodoo_global_string[64];
/** setup BusVoodoo board */
void busvoodoo_setup(void);
/** set safe state by disabling all outputs */
void busvoodoo_safe_state(void);
/** set printf text style
* @param[in] style text style
* @note uses ANSII escape codes
*/
void busvoodoo_text_style(enum busvoodoo_text_style_t style);
/** read voltage from power rail
* @param[in] channel which power rail to read voltage from @ref busvoodoo_adc
* @return voltage, or NaN if channel is invalid (or error happened)
*/
float busvoodoo_vreg_get(uint8_t channel);
#if BUSVOODOO_HARDWARE_VERSION != 2
/** switch 3V3 and 5V power outputs on I/O connector
* @param[in] on switch on (true) or off (false) power output
* @return if switching succeeded. else it means there is a probably a short on one of the outputs
*/
bool busvoodoo_vout_switch(bool on);
/** set voltage on low voltage adjustable voltage regulator
* @note for voltages above 4.85V it will use the 5.0V from USB
* @param[in] voltage voltage to set on adjustable voltage regulator (0, 0.3-4.8, 5V)
* @return voltage output, or NaN if error happened
*/
float busvoodoo_lv_set(float voltage);
/** set voltage on high voltage adjustable voltage regulator
* @param[in] voltage voltage to set on adjustable voltage regulator (0, 3.3-24V)
* @return voltage output, or NaN if error happened
*/
float busvoodoo_hv_set(float voltage);
#endif // BUSVOODOO_HARDWARE_VERSION != 2
/** enable embedded pull-up resistors
* @note the embedded pull-up resistor use the voltage on the LV power rail (set or externally provided)
* @param[in] on enable (true) or disable (false) embedded pull-up resistors
* @return voltage applied on pull-up resistors, or NaN if channel is invalid (or error happened)
*/
float busvoodoo_embedded_pullup(bool on);
/** switch on blue LED
* @note the red LED is handled independently
* @note this will stop the blinking