├── version.txt ├── samples ├── read_write │ ├── README.md │ ├── CMakeLists.txt │ └── main.cpp ├── rtos │ ├── CMakeLists.txt │ └── threadx-demo │ │ └── CMakeLists.txt ├── spi │ ├── CMakeLists.txt │ ├── ADXL345 │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── SPI_With_Arduino │ │ └── CMakeLists.txt ├── lcd │ ├── basic │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── lcd-ball │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── lcd-counter │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── lcd-segment │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── lcd-alphabet │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── lcd-evt-logo │ │ └── CMakeLists.txt │ ├── lcd-more-sections │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── CMakeLists.txt ├── log │ ├── CMakeLists.txt │ └── main.cpp ├── i2c │ ├── CMakeLists.txt │ ├── arduino_source │ │ └── i2c_slave_example │ │ │ └── i2c_slave_example.ino │ └── main.cpp ├── iwdg │ ├── CMakeLists.txt │ └── main.cpp ├── pwm │ ├── CMakeLists.txt │ └── main.cpp ├── rtc │ ├── CMakeLists.txt │ └── main.cpp ├── blink │ ├── CMakeLists.txt │ └── main.cpp ├── button │ ├── CMakeLists.txt │ └── main.cpp ├── canopen │ ├── CMakeLists.txt │ ├── canopen_rpdo │ │ ├── CMakeLists.txt │ │ ├── RPDOCanNode.cpp │ │ └── arduino_tpdo │ │ │ └── arduino_tpdo.ino │ ├── canopen_sample │ │ ├── CMakeLists.txt │ │ ├── TestCanNode.cpp │ │ └── arduino_canopen │ │ │ └── arduino_canopen.ino │ └── canopen_tpdo │ │ ├── CMakeLists.txt │ │ ├── TPDOCanNode.cpp │ │ └── arduino_receive │ │ └── arduino_receive.ino ├── echo │ ├── CMakeLists.txt │ └── main.cpp ├── eeprom │ └── CMakeLists.txt ├── millis │ ├── CMakeLists.txt │ └── main.cpp ├── queue │ └── CMakeLists.txt ├── timer │ ├── CMakeLists.txt │ └── main.cpp ├── encoder │ ├── CMakeLists.txt │ └── main.cpp ├── rtc_timer │ ├── CMakeLists.txt │ └── main.cpp ├── can │ ├── CMakeLists.txt │ ├── loopback │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ └── main.cpp │ ├── back_and_forth │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── arduino_can │ │ │ └── arduino_can.ino │ │ └── main.cpp │ └── multiCAN │ │ ├── README.md │ │ └── CMakeLists.txt ├── thermistor │ ├── CMakeLists.txt │ └── main.cpp ├── button_debounce │ ├── CMakeLists.txt │ └── main.cpp ├── gpio_interrupt │ ├── CMakeLists.txt │ └── main.cpp ├── adc │ ├── CMakeLists.txt │ ├── single_adc.cpp │ └── multi_adc.cpp └── CMakeLists.txt ├── docs ├── source │ ├── _static │ │ ├── .DS_Store │ │ ├── images │ │ │ └── evt_core_layers.png │ │ └── original │ │ │ └── evt_core_layers.drawio │ ├── api │ │ └── stm32f3xx │ │ │ ├── stm32f302x8_dev.rst │ │ │ └── stm32f3xx_io.rst │ ├── glossary.rst │ ├── index.rst │ └── conf.py ├── Makefile ├── requirements.txt └── make.bat ├── libs ├── HALf3 │ ├── include │ │ └── HALf3 │ │ │ ├── stm32f3xx.h │ │ │ ├── cmsis_version.h │ │ │ ├── stm32f3xx_it.h │ │ │ ├── stm32f3xx_hal_spi_ex.h │ │ │ ├── tz_context.h │ │ │ └── system_stm32f3xx.h │ └── README.md └── HALf4 │ ├── README.md │ ├── include │ └── HALf4 │ │ ├── stm32f4xx_it.h │ │ ├── cmsis_version.h │ │ ├── stm32_assert_template.h │ │ ├── stm32f4xx_hal_flash_ramfunc.h │ │ ├── stm32f4xx_hal_ltdc_ex.h │ │ └── system_stm32f4xx.h │ └── CMakeLists.txt ├── .gitmodules ├── src └── core │ ├── io │ ├── ADC.cpp │ ├── PWM.cpp │ ├── GPIO.cpp │ ├── CAN.cpp │ ├── UART.cpp │ ├── types │ │ └── CANMessage.cpp │ └── I2C.cpp │ ├── dev │ ├── storage │ │ └── EEPROM.cpp │ ├── Thermistor.cpp │ ├── button.cpp │ ├── platform │ │ ├── f4xx │ │ │ └── IWDGf4xx.cpp │ │ └── f3xx │ │ │ └── IWDGf3xx.cpp │ ├── LED.cpp │ └── RTCTimer.cpp │ ├── rtos │ ├── Initializable.cpp │ ├── Semaphore.cpp │ ├── Mutex.cpp │ └── EventFlags.cpp │ ├── utils │ ├── platform │ │ ├── f4xx │ │ │ └── timef4xx.cpp │ │ └── f3xx │ │ │ └── timef3xx.cpp │ └── log.cpp │ └── platform │ ├── f3xx │ └── stm32f302x8.cpp │ └── f4xx │ └── stm32f446xx.cpp ├── .gitignore ├── .readthedocs.yaml ├── .vscode ├── extensions.json ├── launch.default.json ├── tasks.default.json └── settings.default.json ├── cmake ├── FindSphinx.cmake ├── evt-core_install.cmake ├── evt-core_build.cmake └── evt-core_clang-format.cmake ├── include └── core │ ├── dev │ ├── IWDG.hpp │ ├── platform │ │ ├── f3xx │ │ │ ├── RTCf3xx.hpp │ │ │ ├── IWDGf3xx.hpp │ │ │ └── Timerf3xx.hpp │ │ └── f4xx │ │ │ ├── RTCf4xx.hpp │ │ │ ├── IWDGf4xx.hpp │ │ │ └── Timerf4xx.hpp │ ├── RTC.hpp │ ├── LED.hpp │ ├── Thermistor.hpp │ ├── button.hpp │ ├── Timer.hpp │ ├── RTCTimer.hpp │ └── storage │ │ └── M24C32.hpp │ ├── platform │ ├── f3xx │ │ └── stm32f3xx.hpp │ └── f4xx │ │ └── stm32f4xx.hpp │ ├── io │ ├── platform │ │ ├── f3xx │ │ │ ├── PWMf3xx.hpp │ │ │ ├── UARTf3xx.hpp │ │ │ ├── I2Cf3xx.hpp │ │ │ ├── GPIOf3xx.hpp │ │ │ └── ADCf3xx.hpp │ │ └── f4xx │ │ │ ├── PWMf4xx.hpp │ │ │ ├── UARTf4xx.hpp │ │ │ ├── I2Cf4xx.hpp │ │ │ └── GPIOf4xx.hpp │ ├── CANDevice.hpp │ ├── ADC.hpp │ └── PWM.hpp │ ├── utils │ ├── time.hpp │ ├── log.hpp │ └── bits.hpp │ └── rtos │ ├── Initializable.hpp │ └── Threadx.hpp ├── Changelog.md ├── .github └── workflows │ └── cmake.yml └── CMakePresets.json /version.txt: -------------------------------------------------------------------------------- 1 | 1.0.0 2 | -------------------------------------------------------------------------------- /samples/read_write/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/rtos/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(threadx-demo) -------------------------------------------------------------------------------- /samples/spi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(ADXL345) 2 | add_subdirectory(SPI_With_Arduino) -------------------------------------------------------------------------------- /docs/source/_static/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RIT-EVT/EVT-core/HEAD/docs/source/_static/.DS_Store -------------------------------------------------------------------------------- /samples/lcd/basic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd main.cpp) 4 | -------------------------------------------------------------------------------- /samples/lcd/lcd-ball/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd-ball main.cpp) 4 | -------------------------------------------------------------------------------- /libs/HALf3/include/HALf3/stm32f3xx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RIT-EVT/EVT-core/HEAD/libs/HALf3/include/HALf3/stm32f3xx.h -------------------------------------------------------------------------------- /samples/lcd/lcd-counter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd-counter main.cpp) 4 | -------------------------------------------------------------------------------- /samples/lcd/lcd-segment/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd-segment main.cpp) 4 | -------------------------------------------------------------------------------- /samples/log/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(log main.cpp) -------------------------------------------------------------------------------- /samples/i2c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(i2c main.cpp) 4 | -------------------------------------------------------------------------------- /samples/iwdg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(iwdg main.cpp) -------------------------------------------------------------------------------- /samples/lcd/lcd-alphabet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd-alphabet main.cpp) 4 | -------------------------------------------------------------------------------- /samples/lcd/lcd-evt-logo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd-evt-logo main.cpp) 4 | -------------------------------------------------------------------------------- /samples/pwm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(pwm main.cpp) 4 | -------------------------------------------------------------------------------- /samples/rtc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(rtc main.cpp) 4 | -------------------------------------------------------------------------------- /samples/blink/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(blink main.cpp) 4 | -------------------------------------------------------------------------------- /samples/button/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(button main.cpp) 4 | -------------------------------------------------------------------------------- /samples/canopen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(canopen_rpdo) 2 | add_subdirectory(canopen_sample) 3 | add_subdirectory(canopen_tpdo) 4 | -------------------------------------------------------------------------------- /samples/echo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(echo main.cpp) 4 | -------------------------------------------------------------------------------- /samples/eeprom/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(eeprom main.cpp) 4 | -------------------------------------------------------------------------------- /samples/millis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(millis main.cpp) 4 | -------------------------------------------------------------------------------- /samples/queue/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(queue main.cpp) 4 | -------------------------------------------------------------------------------- /samples/timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(timer main.cpp) 4 | -------------------------------------------------------------------------------- /samples/encoder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(encoder main.cpp) 4 | -------------------------------------------------------------------------------- /samples/lcd/lcd-more-sections/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(lcd-more-sections main.cpp) 4 | -------------------------------------------------------------------------------- /samples/rtc_timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(rtc_timer main.cpp) -------------------------------------------------------------------------------- /docs/source/_static/images/evt_core_layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RIT-EVT/EVT-core/HEAD/docs/source/_static/images/evt_core_layers.png -------------------------------------------------------------------------------- /samples/can/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Add all samples 2 | add_subdirectory(loopback) 3 | add_subdirectory(back_and_forth) 4 | add_subdirectory(multiCAN) 5 | -------------------------------------------------------------------------------- /samples/read_write/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(read_write main.cpp) 4 | -------------------------------------------------------------------------------- /samples/spi/ADXL345/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(spi_ADXL345 main.cpp) -------------------------------------------------------------------------------- /samples/spi/SPI_With_Arduino/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(spi main.cpp) -------------------------------------------------------------------------------- /samples/thermistor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(thermistor main.cpp) 4 | -------------------------------------------------------------------------------- /samples/can/loopback/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(loopback main.cpp) 4 | -------------------------------------------------------------------------------- /samples/button_debounce/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(button_debounce main.cpp) 4 | -------------------------------------------------------------------------------- /samples/gpio_interrupt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(gpio_interrupt main.cpp) 4 | -------------------------------------------------------------------------------- /samples/can/back_and_forth/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(back_and_forth main.cpp) 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libs/canopen"] 2 | path = libs/canopen 3 | url = ../canopen-stack.git 4 | [submodule "libs/threadx"] 5 | path = libs/threadx 6 | url = ../threadx.git 7 | -------------------------------------------------------------------------------- /samples/adc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) 2 | 3 | make_exe(single_adc single_adc.cpp) 4 | make_exe(multi_adc multi_adc.cpp) 5 | -------------------------------------------------------------------------------- /src/core/io/ADC.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::io { 4 | 5 | ADC::ADC(Pin pin, ADCPeriph adcPeriph) : pin(pin), adcPeriph(adcPeriph) {} 6 | 7 | } // namespace core::io 8 | -------------------------------------------------------------------------------- /samples/canopen/canopen_rpdo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | set( SAMPLE_SOURCES main.cpp RPDOCanNode.cpp) 4 | make_exe(canopen_rpdo "${SAMPLE_SOURCES}") 5 | 6 | -------------------------------------------------------------------------------- /samples/canopen/canopen_sample/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | set( SAMPLE_SOURCES main.cpp TestCanNode.cpp) 4 | make_exe(canopen_sample "${SAMPLE_SOURCES}") 5 | 6 | -------------------------------------------------------------------------------- /samples/canopen/canopen_tpdo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(../../../cmake/evt-core_build.cmake) 2 | 3 | set( SAMPLE_SOURCES main.cpp TPDOCanNode.cpp) 4 | make_exe(canopen_tpdo "${SAMPLE_SOURCES}") 5 | 6 | -------------------------------------------------------------------------------- /src/core/io/PWM.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::io { 4 | 5 | PWM::PWM(Pin pin) { 6 | this->pin = pin; 7 | this->dutyCycle = 0; 8 | this->period = 0; 9 | } 10 | 11 | } // namespace core::io 12 | -------------------------------------------------------------------------------- /samples/lcd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(basic) 2 | add_subdirectory(lcd-alphabet) 3 | add_subdirectory(lcd-ball) 4 | add_subdirectory(lcd-counter) 5 | add_subdirectory(lcd-evt-logo) 6 | add_subdirectory(lcd-segment) 7 | add_subdirectory(lcd-more-sections) 8 | -------------------------------------------------------------------------------- /samples/can/multiCAN/README.md: -------------------------------------------------------------------------------- 1 | # MultiCAN 2 | 3 | This sample is intended to show the ability to use dual CANbus interfaces on 4 | the STM32F446xx. The two CAN interfaces can be connected together on the same 5 | network as a more complicated loopback with transceivers 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build files 2 | build*/ 3 | html/ 4 | latex/ 5 | compile_commands.json 6 | cmake-build-debug/ 7 | 8 | # Virtual environments 9 | venv/ 10 | 11 | # IDE Files 12 | .idea/ 13 | .vscode/ 14 | .cache/ 15 | .settings/ 16 | .clangd 17 | 18 | # macOS files 19 | .DS_Store 20 | -------------------------------------------------------------------------------- /samples/rtos/threadx-demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/evt-core_build.cmake) 2 | 3 | if(USE_RTOS) 4 | make_exe(threadx-demo main.cpp) 5 | else() 6 | add_custom_target(threadx-demo ${CMAKE_COMMAND} -E cmake_echo_color --red "RTOS is not on") 7 | endif() -------------------------------------------------------------------------------- /src/core/dev/storage/EEPROM.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains generic implmentations for some of the EEPROM funcitonality. 3 | * Some hardware has the ability to implement the functionality in this 4 | * file so specific implementations of the EEPROM driver may override these 5 | * methods for a hardware speedup. 6 | */ 7 | 8 | namespace core::dev {} -------------------------------------------------------------------------------- /samples/can/loopback/README.md: -------------------------------------------------------------------------------- 1 | CAN Loopback 2 | 3 | For this sample the device is setup for loopback communication. In this state 4 | the device will be able to communicate with itself and not require access to 5 | a full CAN network nor CAN transciever. This is helpful for validating basic 6 | CAN TX/RX, but not for validating full CAN network communication. 7 | -------------------------------------------------------------------------------- /samples/can/multiCAN/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/evt-core_build.cmake) 2 | 3 | if(COMPDEFS MATCHES "(.*)STM32F4xx(.*)") 4 | make_exe(multiCAN main.cpp) 5 | else() 6 | add_custom_target(multiCAN ${CMAKE_COMMAND} -E cmake_echo_color --red "multiCAN only works on an STM32F446 due to dual CAN interfaces") 7 | endif() 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/core/io/GPIO.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::io { 4 | 5 | // Setup instance variables 6 | GPIO::GPIO(Pin pin) { 7 | this->pin = pin; 8 | } 9 | 10 | GPIO::GPIO(Pin pin, Direction direction, Pull pull) { 11 | this->pin = pin; 12 | this->direction = direction; 13 | this->pull = pull; 14 | } 15 | 16 | } // namespace core::io 17 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | # Build from the docs/ directory with Sphinx 4 | sphinx: 5 | configuration: docs/source/conf.py 6 | 7 | build: 8 | image: latest 9 | apt_packages: 10 | - doxygen 11 | 12 | # Explicitly set the version of Python and its requirements 13 | python: 14 | version: 3.7 15 | install: 16 | - requirements: docs/requirements.txt 17 | -------------------------------------------------------------------------------- /src/core/dev/Thermistor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::dev { 4 | 5 | Thermistor::Thermistor(core::io::ADC& adc, uint32_t (*conversion)(uint32_t)) : adc(adc), conversion(conversion) {} 6 | 7 | uint32_t Thermistor::getTempCelcius() { 8 | return conversion(adc.readRaw()); 9 | } 10 | 11 | uint32_t Thermistor::getRawADC() { 12 | return adc.readRaw(); 13 | } 14 | 15 | } // namespace core::dev 16 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "eamodio.gitlens", 4 | "llvm-vs-code-extensions.vscode-clangd", 5 | "ms-vscode.cmake-tools", 6 | "stmicroelectronics.stm32cube-ide-debug-stlink-gdbserver", 7 | "stmicroelectronics.stm32cube-ide-registers", 8 | "seunlanlege.action-buttons", 9 | "rioj7.command-variable", 10 | "spadin.config-defaults", 11 | ], 12 | } -------------------------------------------------------------------------------- /libs/HALf3/README.md: -------------------------------------------------------------------------------- 1 | # Hardware Abstraction Layer (HAL) 2 | 3 | ## Introduction 4 | 5 | This project is a CMake wrapper for the HAL provided by STM. The code itself 6 | is not created by EVT, but the CMake wrapper that allows the code to be used 7 | as a library is. 8 | 9 | The goal of this is to allow easier inclusion of the HAL into the EVT core 10 | library while maintaining a seperation between EVT code and STM provided code. 11 | -------------------------------------------------------------------------------- /libs/HALf4/README.md: -------------------------------------------------------------------------------- 1 | # Hardware Abstraction Layer (HAL) 2 | 3 | ## Introduction 4 | 5 | This project is a CMake wrapper for the HAL provided by STM. The code itself 6 | is not created by EVT, but the CMake wrapper that allows the code to be used 7 | as a library is. 8 | 9 | The goal of this is to allow easier inclusion of the HAL into the EVT core 10 | library while maintaining a seperation between EVT code and STM provided code. 11 | -------------------------------------------------------------------------------- /src/core/io/CAN.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace core::io { 6 | 7 | CAN::CAN(Pin txPin, Pin rxPin, bool loopbackEnabled) : txPin(txPin), rxPin(rxPin), loopbackEnabled(loopbackEnabled) { 8 | this->handler = nullptr; 9 | this->priv = nullptr; 10 | } 11 | 12 | void CAN::addIRQHandler(void (*handler)(CANMessage&, void*), void* priv) { 13 | this->handler = handler; 14 | this->priv = priv; 15 | } 16 | 17 | } // namespace core::io 18 | -------------------------------------------------------------------------------- /cmake/FindSphinx.cmake: -------------------------------------------------------------------------------- 1 | #Look for an executable called sphinx-build 2 | find_program(SPHINX_EXECUTABLE 3 | NAMES sphinx-build 4 | DOC "Path to sphinx-build executable") 5 | 6 | include(FindPackageHandleStandardArgs) 7 | 8 | #Handle standard arguments to find_package like REQUIRED and QUIET 9 | find_package_handle_standard_args(Sphinx 10 | "Failed to find sphinx-build executable" 11 | SPHINX_EXECUTABLE) 12 | -------------------------------------------------------------------------------- /samples/can/back_and_forth/README.md: -------------------------------------------------------------------------------- 1 | # CAN Back and Forth 2 | 3 | This sample is intended for use between two CAN devices. The two devices need 4 | to be connected on a CAN network (with transcievers). Two devices with this 5 | code on board can communicate with each other. Also included is an Arduino 6 | sample code that should work with most CAN shields. The Arduino code operates 7 | similar to the EVT-core code spitting out CAN messages and waiting for 8 | a CAN message to come in before writing another message. 9 | -------------------------------------------------------------------------------- /docs/source/api/stm32f3xx/stm32f302x8_dev.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | STM32F302x8 DEV 3 | =============== 4 | 5 | Below are the devices that are interal to the STM32F302x8 MCU. As such these 6 | devices are implemented directly for the STM32F302x8. 7 | 8 | IWDG 9 | ==== 10 | 11 | .. doxygenclass:: core::dev::IWDGf3xx 12 | :members: 13 | 14 | RTC 15 | === 16 | 17 | .. doxygenclass:: core::dev::RTCf3xx 18 | :members: 19 | 20 | Timer 21 | ===== 22 | 23 | .. doxygenclass:: core::dev::Timerf3xx 24 | :members: 25 | 26 | -------------------------------------------------------------------------------- /include/core/dev/IWDG.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_IWDG_ 2 | #define _EVT_IWDG_ 3 | 4 | namespace core::dev { 5 | 6 | /** 7 | * The IWDG is the independent watchdog, which is used to detect software failures. 8 | * This class represents features common to watchdog timers. 9 | */ 10 | class IWDG { 11 | public: 12 | /** 13 | * Initializes and activates the watchdog timer. 14 | */ 15 | virtual void init() = 0; 16 | 17 | /** 18 | * Refreshes the watchdog timer. 19 | */ 20 | virtual void refresh() = 0; 21 | }; 22 | 23 | } // namespace core::dev 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /samples/canopen/canopen_sample/TestCanNode.cpp: -------------------------------------------------------------------------------- 1 | #include "TestCanNode.hpp" 2 | 3 | TestCanNode::TestCanNode() { 4 | sampleData = 0; 5 | } 6 | 7 | void TestCanNode::setSampleData(uint8_t newValue) { 8 | this->sampleData = newValue; 9 | } 10 | 11 | uint8_t TestCanNode::getSampleData() { 12 | return sampleData; 13 | } 14 | 15 | CO_OBJ_T* TestCanNode::getObjectDictionary() { 16 | return &objectDictionary[0]; 17 | } 18 | 19 | uint8_t TestCanNode::getNumElements() { 20 | return OBJECT_DICTIONARY_SIZE; 21 | } 22 | uint8_t TestCanNode::getNodeID() { 23 | return NODE_ID; 24 | } 25 | -------------------------------------------------------------------------------- /src/core/rtos/Initializable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::rtos { 4 | 5 | void Initializable::getName(char* destination, size_t size) { 6 | if (size > INITIALIZABLE_NAME_MAX_LENGTH) { 7 | size = INITIALIZABLE_NAME_MAX_LENGTH; 8 | } 9 | strncpy(destination, this->name, size); 10 | destination[size - 1] = '\0'; 11 | } 12 | 13 | Initializable::Initializable(char* name) { 14 | strncpy(this->name, name, INITIALIZABLE_NAME_MAX_LENGTH); 15 | this->name[INITIALIZABLE_NAME_MAX_LENGTH - 1] = '\0'; 16 | } 17 | 18 | } // namespace core::rtos 19 | -------------------------------------------------------------------------------- /src/core/utils/platform/f4xx/timef4xx.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * STM32F4xx implementation of the time functionality. This code is designed 3 | * only to run on the STMF3xx. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace core::time { 13 | /** 14 | * Calls HAL wait, assumes HAL_Init() has been called 15 | */ 16 | void wait(uint32_t ms) { 17 | HAL_Delay(ms); 18 | } 19 | 20 | /** 21 | * Reads the system ticks from HAL_GetTicks 22 | */ 23 | uint32_t millis() { 24 | return HAL_GetTick(); 25 | } 26 | } // namespace core::time 27 | -------------------------------------------------------------------------------- /include/core/platform/f3xx/stm32f3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_STM32F3xx_ 2 | #define _EVT_STM32F3xx_ 3 | 4 | #include 5 | 6 | namespace core::platform { 7 | 8 | // Interrupt Priority Mappings. 0 is high and 15 is low 9 | constexpr uint32_t CAN_INTERRUPT_PRIORITY = 4; 10 | constexpr uint32_t ADC_INTERRUPT_PRIORITY = 5; 11 | constexpr uint32_t TIMER_INTERRUPT_PRIORITY = 9; 12 | constexpr uint32_t GPIO_INTERRUPT_PRIORITY = 10; 13 | 14 | /** 15 | * Handles system level initialization of the STM32F302x8. This makes a 16 | * series of calls into the HAL to enable system peripherals and enable 17 | * all required clock. 18 | */ 19 | void stm32f3xx_init(); 20 | 21 | } // namespace core::platform 22 | #endif 23 | -------------------------------------------------------------------------------- /src/core/dev/button.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace core::dev { 5 | Button::Button(io::GPIO& gpio, io::GPIO::State pressedState) : gpio(gpio), pressedState(pressedState) { 6 | this->timeSinceLastPress = 0; 7 | } 8 | 9 | io::GPIO::State Button::getState() { 10 | return this->gpio.readPin(); 11 | } 12 | 13 | bool Button::debounce(uint32_t debounceTime) { 14 | if (time::millis() - this->timeSinceLastPress > debounceTime) { 15 | if (this->getState() == pressedState) { 16 | this->timeSinceLastPress = time::millis(); 17 | return true; 18 | } 19 | } 20 | 21 | return false; 22 | } 23 | 24 | } // namespace core::dev -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | alabaster==0.7.12 2 | Babel==2.9.1 3 | breathe==4.30.0 4 | certifi==2021.5.30 5 | charset-normalizer==2.0.4 6 | cpplint==1.5.4 7 | docutils==0.16 8 | flake8==3.9.2 9 | idna==3.2 10 | imagesize==1.2.0 11 | Jinja2==3.0.1 12 | MarkupSafe==2.0.1 13 | mccabe==0.6.1 14 | packaging==21.0 15 | pycodestyle==2.7.0 16 | pyflakes==2.3.1 17 | Pygments==2.10.0 18 | pyparsing==2.4.7 19 | pytz==2021.1 20 | requests==2.26.0 21 | snowballstemmer==2.1.0 22 | Sphinx==4.1.2 23 | sphinx-rtd-theme==0.5.2 24 | sphinxcontrib-applehelp==1.0.2 25 | sphinxcontrib-devhelp==1.0.2 26 | sphinxcontrib-htmlhelp==2.0.0 27 | sphinxcontrib-jsmath==1.0.1 28 | sphinxcontrib-qthelp==1.0.3 29 | sphinxcontrib-serializinghtml==1.1.5 30 | urllib3==1.26.6 31 | -------------------------------------------------------------------------------- /samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Add all samples 2 | add_subdirectory(adc) 3 | add_subdirectory(blink) 4 | add_subdirectory(button) 5 | add_subdirectory(button_debounce) 6 | add_subdirectory(can) 7 | add_subdirectory(canopen) 8 | add_subdirectory(echo) 9 | add_subdirectory(eeprom) 10 | add_subdirectory(encoder) 11 | add_subdirectory(gpio_interrupt) 12 | add_subdirectory(i2c) 13 | add_subdirectory(iwdg) 14 | add_subdirectory(lcd) 15 | add_subdirectory(log) 16 | add_subdirectory(millis) 17 | add_subdirectory(pwm) 18 | add_subdirectory(queue) 19 | add_subdirectory(read_write) 20 | add_subdirectory(rtc) 21 | add_subdirectory(rtc_timer) 22 | add_subdirectory(rtos) 23 | add_subdirectory(thermistor) 24 | add_subdirectory(timer) 25 | add_subdirectory(spi) 26 | -------------------------------------------------------------------------------- /samples/pwm/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example shows off a basic PWM signal. You will need to use a logic 3 | * analyzer to see the generated square wave. 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | namespace io = core::io; 10 | namespace time = core::time; 11 | 12 | int main() { 13 | // Initialize system 14 | core::platform::init(); 15 | 16 | io::PWM& pwm = io::getPWM(); 17 | // 1000000 microseconds (1 second) period 18 | pwm.setPeriod(1000000); 19 | // 50 % duty cycle 20 | pwm.setDutyCycle(50); 21 | 22 | while (1) { 23 | time::wait(5000); 24 | pwm.setDutyCycle(70); 25 | time::wait(5000); 26 | pwm.setDutyCycle(30); 27 | } 28 | } -------------------------------------------------------------------------------- /src/core/dev/platform/f4xx/IWDGf4xx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::dev { 4 | 5 | // According to a time formula in the documentation with the set prescaler, 6 | // the ratio of counter ticks to milliseconds should be about 1:8. In testing, 7 | // we found this to have an error of about 1 second 8 | IWDGf4xx::IWDGf4xx(uint32_t ms) 9 | : halIWDG{ 10 | IWDG1, 11 | { 12 | IWDG_PRESCALER_256, 13 | ms / 8 - 1, 14 | }, 15 | } {} 16 | 17 | void IWDGf4xx::init() { 18 | HAL_IWDG_Init(&halIWDG); 19 | isActive = true; 20 | } 21 | 22 | void IWDGf4xx::refresh() { 23 | if (isActive) { 24 | HAL_IWDG_Refresh(&halIWDG); 25 | } 26 | } 27 | 28 | } // namespace core::dev 29 | -------------------------------------------------------------------------------- /samples/echo/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a basic sample of using the UART module. The program provides a 3 | * basic echo functionality where the uart will write back whatever the user 4 | * enters. 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | namespace io = core::io; 11 | 12 | int main() { 13 | // Initialize system 14 | core::platform::init(); 15 | 16 | // Setup UART 17 | io::UART& uart = io::getUART(9600); 18 | 19 | // String to store user input 20 | char buf[100]; 21 | 22 | while (1) { 23 | // Read user input 24 | uart.printf("Enter message: "); 25 | uart.gets(buf, 100); 26 | uart.printf("\n\recho: %s\n\r", buf); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/core/dev/platform/f3xx/IWDGf3xx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::dev { 4 | 5 | // According to a time formula in the documentation with the set prescaler, 6 | // the ratio of counter ticks to milliseconds should be about 1:8. In testing, 7 | // we found this to have an error of about 1 second 8 | IWDGf3xx::IWDGf3xx(uint32_t ms) 9 | : halIWDG{ 10 | IWDG1, 11 | { 12 | IWDG_PRESCALER_256, 13 | ms / 8 - 1, 14 | ms / 8 - 1, 15 | }, 16 | } {} 17 | 18 | void IWDGf3xx::init() { 19 | HAL_IWDG_Init(&halIWDG); 20 | isActive = true; 21 | } 22 | 23 | void IWDGf3xx::refresh() { 24 | if (isActive) { 25 | HAL_IWDG_Refresh(&halIWDG); 26 | } 27 | } 28 | 29 | } // namespace core::dev 30 | -------------------------------------------------------------------------------- /include/core/platform/f4xx/stm32f4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_STM32F4xx_ 2 | #define _EVT_STM32F4xx_ 3 | 4 | namespace core::platform { 5 | 6 | // stm32f4xx_init() sets clock speed to 50MHz 7 | constexpr uint32_t CLK_SPEED = 50000000; 8 | 9 | // Interrupt Priority Mappings. 0 is high and 15 is low 10 | constexpr uint32_t CAN_INTERRUPT_PRIORITY = 4; 11 | constexpr uint32_t ADC_INTERRUPT_PRIORITY = 5; 12 | constexpr uint32_t TIMER_INTERRUPT_PRIORITY = 9; 13 | constexpr uint32_t GPIO_INTERRUPT_PRIORITY = 10; 14 | 15 | /** 16 | * Handles system level initialization of the STM32F4xx. This makes a 17 | * series of calls into the HAL to enable system peripherals and enable 18 | * all required clock. 19 | */ 20 | void stm32f4xx_init(); 21 | void Error_Handler(void); 22 | 23 | } // namespace core::platform 24 | #endif 25 | -------------------------------------------------------------------------------- /samples/canopen/canopen_rpdo/RPDOCanNode.cpp: -------------------------------------------------------------------------------- 1 | #include "RPDOCanNode.hpp" 2 | 3 | RPDOCanNode::RPDOCanNode() { 4 | sampleDataA = 0; 5 | sampleDataB = 0; 6 | } 7 | 8 | CO_OBJ_T* RPDOCanNode::getObjectDictionary() { 9 | return &objectDictionary[0]; 10 | } 11 | 12 | uint8_t RPDOCanNode::getNumElements() { 13 | return OBJECT_DICTIONARY_SIZE + 1; 14 | } 15 | 16 | void RPDOCanNode::setSampleDataA(uint8_t newValue) { 17 | this->sampleDataA = newValue; 18 | } 19 | 20 | uint8_t RPDOCanNode::getSampleDataA() { 21 | return sampleDataA; 22 | } 23 | 24 | void RPDOCanNode::setSampleDataB(uint16_t newValue) { 25 | this->sampleDataB = newValue; 26 | } 27 | 28 | uint16_t RPDOCanNode::getSampleDataB() { 29 | return sampleDataB; 30 | } 31 | uint8_t RPDOCanNode::getNodeID() { 32 | return NODE_ID; 33 | } 34 | -------------------------------------------------------------------------------- /src/core/utils/platform/f3xx/timef3xx.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * STMF3xx implementation of the time functionality. This code is designed 3 | * only to run on the STMF3xx. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace core::time { 13 | /** 14 | * Calls HAL wait, assumes HAL_Init() has been called 15 | */ 16 | void wait(uint32_t ms) { 17 | // TODO: Remove need for this first time call 18 | static bool isFirst = true; 19 | if (isFirst) { 20 | HAL_Init(); 21 | SysTick_Handler(); 22 | } 23 | 24 | HAL_Delay(ms); 25 | } 26 | 27 | /** 28 | * Reads the system ticks from HAL_GetTicks 29 | */ 30 | uint32_t millis() { 31 | return HAL_GetTick(); 32 | } 33 | } // namespace core::time 34 | -------------------------------------------------------------------------------- /include/core/dev/platform/f3xx/RTCf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_RTCf3xx_ 2 | #define _EVT_RTCf3xx_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace core::dev { 9 | 10 | /** 11 | * RTC implementation that makes use of the on-board real time clock 12 | * on STM32f3xx MCUs. 13 | * 14 | * The onboard RTC can be kept up to date with a coin cell battery. 15 | */ 16 | class RTCf3xx : public RTC { 17 | public: 18 | /** 19 | * Empty constructor. Will startup the RTC. 20 | */ 21 | RTCf3xx(); 22 | 23 | void getTime(core::time::TimeStamp& time) override; 24 | 25 | uint32_t getTime() override; 26 | 27 | void setTime(core::time::TimeStamp& time) override; 28 | 29 | private: 30 | /** Instance of the HAL RTC interface */ 31 | RTC_HandleTypeDef halRTC; 32 | }; 33 | 34 | } // namespace core::dev 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/core/dev/platform/f4xx/RTCf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_RTCf4xx_ 2 | #define _EVT_RTCf4xx_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace core::dev { 9 | 10 | /** 11 | * RTC implementation that makes use of the on-board real time clock 12 | * on STM32f3xx MCUs. 13 | * 14 | * The onboard RTC can be kept up to date with a coin cell battery. 15 | */ 16 | class RTCf4xx : public RTC { 17 | public: 18 | /** 19 | * Empty constructor. Will startup the RTC. 20 | */ 21 | RTCf4xx(); 22 | 23 | void getTime(core::time::TimeStamp& time) override; 24 | 25 | uint32_t getTime() override; 26 | 27 | void setTime(core::time::TimeStamp& time) override; 28 | 29 | private: 30 | /** Instance of the HAL RTC interface */ 31 | RTC_HandleTypeDef halRTC; 32 | }; 33 | 34 | } // namespace core::dev 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /docs/source/api/stm32f3xx/stm32f3xx_io.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | STM32F3xx IO 3 | ============ 4 | 5 | 6 | Below is the implementation documentation for the IO supported by the 7 | STM32F302x8 and the STM32F334x8. Both platforms use the same HAL and thus 8 | share similar implementations in EVT-core. 9 | 10 | 11 | ADC 12 | === 13 | 14 | .. doxygenclass:: core::io::ADCf3xx 15 | :members: 16 | 17 | CAN 18 | === 19 | 20 | .. doxygenclass:: core::io::CANf3xx 21 | :members: 22 | 23 | GPIO 24 | ==== 25 | 26 | .. doxygenclass:: core::io::GPIOf3xx 27 | :members: 28 | 29 | I2C 30 | === 31 | 32 | .. doxygenclass:: core::io::I2Cf3xx 33 | :members: 34 | 35 | PWM 36 | === 37 | 38 | .. doxygenclass:: core::io::PWMf3xx 39 | :members: 40 | 41 | SPI 42 | === 43 | 44 | .. doxygenclass:: core::io::SPIf3xx 45 | :members: 46 | 47 | UART 48 | ==== 49 | 50 | .. doxygenclass:: core::io::UARTf3xx 51 | :members: 52 | 53 | -------------------------------------------------------------------------------- /include/core/io/platform/f3xx/PWMf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_PWMf3xx_ 2 | #define _EVT_PWMf3xx_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace core::io { 11 | 12 | class PWMf3xx : public PWM { 13 | public: 14 | /** 15 | * Setup the given pin for PWM usage. 16 | * 17 | * @param pin[in] The pin to setup for PWM 18 | */ 19 | PWMf3xx(Pin pin); 20 | 21 | void setDutyCycle(uint32_t dutyCycle); 22 | 23 | void setPeriod(uint32_t period); 24 | 25 | uint32_t getDutyCycle(); 26 | 27 | uint32_t getPeriod(); 28 | 29 | private: 30 | /// HAL timer representation 31 | TIM_HandleTypeDef halTIM; 32 | /// Channel identification 33 | uint32_t halTIMChannelID; 34 | /// HAL channel representation 35 | TIM_OC_InitTypeDef halChannel; 36 | }; 37 | 38 | } // namespace core::io 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /include/core/io/platform/f4xx/PWMf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_PWMf4xx_ 2 | #define _EVT_PWMf4xx_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace core::io { 11 | 12 | class PWMf4xx : public PWM { 13 | public: 14 | /** 15 | * Setup the given pin for PWM usage. 16 | * 17 | * @param pin[in] The pin to setup for PWM 18 | */ 19 | PWMf4xx(Pin pin); 20 | 21 | void setDutyCycle(uint32_t dutyCycle) override; 22 | 23 | void setPeriod(uint32_t period) override; 24 | 25 | uint32_t getDutyCycle() override; 26 | 27 | uint32_t getPeriod() override; 28 | 29 | private: 30 | /// HAL timer representation 31 | TIM_HandleTypeDef halTIM; 32 | /// Channel identification 33 | uint32_t halTIMChannelID; 34 | /// HAL channel representation 35 | TIM_OC_InitTypeDef halChannel; 36 | }; 37 | 38 | } // namespace core::io 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /samples/canopen/canopen_tpdo/TPDOCanNode.cpp: -------------------------------------------------------------------------------- 1 | #include "TPDOCanNode.hpp" 2 | 3 | TPDOCanNode::TPDOCanNode() { 4 | sampleDataA = 0; 5 | sampleDataB = 1; 6 | } 7 | 8 | void TPDOCanNode::setSampleDataA(uint8_t newValue) { 9 | this->sampleDataA = newValue; 10 | } 11 | 12 | uint8_t TPDOCanNode::getSampleDataA() { 13 | return sampleDataA; 14 | } 15 | 16 | void TPDOCanNode::setSampleDataB(uint16_t newValue) { 17 | this->sampleDataB = newValue; 18 | } 19 | 20 | uint16_t TPDOCanNode::getSampleDataB() { 21 | return sampleDataB; 22 | } 23 | 24 | void TPDOCanNode::update() { 25 | sampleDataA++; 26 | if (sampleDataA % 20 == 0) { 27 | sampleDataB *= 3; 28 | } 29 | } 30 | 31 | CO_OBJ_T* TPDOCanNode::getObjectDictionary() { 32 | return &objectDictionary[0]; 33 | } 34 | 35 | uint8_t TPDOCanNode::getNumElements() { 36 | return OBJECT_DICTIONARY_SIZE; 37 | } 38 | 39 | uint8_t TPDOCanNode::getNodeID() { 40 | return NODE_ID; 41 | } 42 | -------------------------------------------------------------------------------- /include/core/dev/RTC.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_RTC_ 2 | #define _EVT_RTC_ 3 | 4 | #include 5 | 6 | namespace core::dev { 7 | 8 | /** 9 | * The RTC is the real time clock interface. This class represents features 10 | * common acrross real time clocks. 11 | */ 12 | class RTC { 13 | public: 14 | /** 15 | * Get the current time as determined by the real time clock. 16 | * 17 | * @param[out] time The time struct to populate 18 | */ 19 | virtual void getTime(core::time::TimeStamp& time) = 0; 20 | 21 | /** 22 | * Get the timestamp since epoch in seconds 23 | * 24 | * @return The time since epoch as determined by the RTC 25 | */ 26 | virtual uint32_t getTime() = 0; 27 | 28 | /** 29 | * Set the time of the real time clock. 30 | * 31 | * @param[in] time The time to set the RTC to use. 32 | */ 33 | virtual void setTime(core::time::TimeStamp& time) = 0; 34 | }; 35 | 36 | } // namespace core::dev 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /samples/button/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace dev = core::dev; 8 | namespace io = core::io; 9 | namespace time = core::time; 10 | 11 | int main() { 12 | // Initialize system 13 | core::platform::init(); 14 | 15 | // Setup UART 16 | io::UART& uart = io::getUART(9600); 17 | io::GPIO& ledGPIO = io::getGPIO(); 18 | io::GPIO& buttonGPIO = io::getGPIO(); 19 | 20 | dev::LED led(ledGPIO, dev::LED::ActiveState::HIGH); 21 | 22 | dev::Button button = dev::Button(buttonGPIO); 23 | 24 | while (true) { 25 | io::GPIO::State buttonStatus = button.getState(); 26 | uart.printf("Button Status: %d \n", buttonStatus); 27 | 28 | led.setState(buttonStatus); 29 | 30 | time::wait(100); 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /samples/millis/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example calls the millis function and prints out the result. Each 3 | * result should be ~500ms off from each other 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace io = core::io; 13 | namespace dev = core::dev; 14 | namespace time = core::time; 15 | 16 | int main() { 17 | // Initialize system 18 | core::platform::init(); 19 | 20 | // Setup the GPIO pin. 21 | // Notice that the pin used is called "LED". Each platform has a dedicated 22 | // LED pin, for the f3xx that is PB_13. 23 | io::UART& uart = io::getUART(9600); 24 | 25 | time::wait(500); 26 | 27 | while (1) { 28 | uart.printf("millis() -> %d\r\n", time::millis()); 29 | // Wait half a second 30 | time::wait(500); 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /samples/iwdg/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example of IWDG functionality. The timer is refreshed 3 times in a loop, 3 | * then hits an infinite loop in the code which triggers a system reset. 4 | */ 5 | #include 6 | #include 7 | 8 | namespace io = core::io; 9 | namespace dev = core::dev; 10 | namespace time = core::time; 11 | 12 | int main() { 13 | // Initialize system 14 | core::platform::init(); 15 | io::UART& uart = io::getUART(9600); 16 | 17 | // Start watchdog 18 | dev::IWDG& iwdg = dev::getIWDG(5000); 19 | iwdg.init(); 20 | 21 | uart.printf("Starting IWDG test...\n\r\n\r"); 22 | 23 | // Refresh watchdog at regular intervals 24 | for (int i = 0; i < 3; i++) { 25 | time::wait(500); 26 | iwdg.refresh(); 27 | uart.printf("IWDG refreshed\n\r"); 28 | } 29 | 30 | // Infinite loop represents an error, board should reset after the watchdog times out 31 | while (1) 32 | ; 33 | } -------------------------------------------------------------------------------- /samples/read_write/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example shows off using GPIO pins for input and output. One GPIO is 3 | * setup as an input and the state of that GPIO is reflected in the state of 4 | * the other GPIO connected to an LED. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace io = core::io; 13 | namespace dev = core::dev; 14 | namespace time = core::time; 15 | 16 | int main() { 17 | // Initialize system 18 | core::platform::init(); 19 | 20 | // Setup the GPIO input pin 21 | io::GPIO& inputGPIO = io::getGPIO(io::GPIO::Direction::INPUT); 22 | 23 | // Setup the GPIO output pin 24 | io::GPIO& ledGPIO = io::getGPIO(); 25 | dev::LED led(ledGPIO, dev::LED::ActiveState::HIGH); 26 | 27 | while (1) { 28 | io::GPIO::State state = inputGPIO.readPin(); 29 | led.setState(state); 30 | 31 | time::wait(10); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /include/core/dev/platform/f3xx/IWDGf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_IWDGf3xx_ 2 | #define _EVT_IWDGf3xx_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace core::dev { 9 | 10 | /** 11 | * Implementation of the independent watchdog for STM32f3xx MCUs, which 12 | * use the low-speed internal RC oscillator to detect software failures and 13 | * trigger a reset. 14 | */ 15 | class IWDGf3xx : public IWDG { 16 | public: 17 | /** 18 | * Constructor for the IWDG, which also starts the watchdog timer. 19 | * 20 | * @param ms Time in milliseconds before the IWDG triggers a reset, 21 | * must be a value between 8 and 32768 ms. 22 | */ 23 | explicit IWDGf3xx(uint32_t ms); 24 | 25 | void init() override; 26 | 27 | void refresh() override; 28 | 29 | private: 30 | /** Instance of the HAL IWDG */ 31 | IWDG_HandleTypeDef halIWDG; 32 | 33 | /** Whether the watchdog timer is active */ 34 | bool isActive = false; 35 | }; 36 | 37 | } // namespace core::dev 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/core/dev/LED.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::dev { 4 | 5 | LED::LED(core::io::GPIO& gpio, LED::ActiveState activeState) : gpio(gpio) { 6 | this->setState(core::io::GPIO::State::LOW); 7 | } 8 | 9 | void LED::toggle() { 10 | core::io::GPIO::State currentState = this->gpio.readPin(); 11 | 12 | if (core::io::GPIO::State::LOW == currentState) { 13 | this->gpio.writePin(core::io::GPIO::State::HIGH); 14 | } else { 15 | this->gpio.writePin(core::io::GPIO::State::LOW); 16 | } 17 | } 18 | 19 | void LED::setState(core::io::GPIO::State state) { 20 | // if the LED is active high, it's state follows from pin setting 21 | if (this->activeState == ActiveState::HIGH) { 22 | this->gpio.writePin(state); 23 | } else { 24 | if (state == core::io::GPIO::State::HIGH) { 25 | this->gpio.writePin(core::io::GPIO::State::LOW); 26 | } else { 27 | this->gpio.writePin(core::io::GPIO::State::HIGH); 28 | } 29 | } 30 | } 31 | 32 | } // namespace core::dev 33 | -------------------------------------------------------------------------------- /include/core/dev/platform/f4xx/IWDGf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVT_IWDGF4XX_HPP 2 | #define EVT_IWDGF4XX_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace core::dev { 9 | 10 | /** 11 | * Implementation of the independent watchdog for STM32f3xx MCUs, which 12 | * use the low-speed internal RC oscillator to detect software failures and 13 | * trigger a reset. 14 | */ 15 | class IWDGf4xx : public IWDG { 16 | public: 17 | /** 18 | * Constructor for the IWDG, which also starts the watchdog timer. 19 | * 20 | * @param ms Time in milliseconds before the IWDG triggers a reset, 21 | * must be a value between 8 and 32768 ms. 22 | */ 23 | explicit IWDGf4xx(uint32_t ms); 24 | 25 | void init() override; 26 | 27 | void refresh() override; 28 | 29 | private: 30 | /** Instance of the HAL IWDG */ 31 | IWDG_HandleTypeDef halIWDG; 32 | 33 | /** Whether the watchdog timer is active */ 34 | bool isActive = false; 35 | }; 36 | 37 | } // namespace core::dev 38 | 39 | #endif // EVT_IWDGF4XX_HPP 40 | -------------------------------------------------------------------------------- /src/core/dev/RTCTimer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::dev { 4 | 5 | RTCTimer::RTCTimer(RTC& r) : rtc(r) { 6 | time = 0; 7 | setPeriod(1000); 8 | startTime = rtc.getTime(); 9 | } 10 | 11 | RTCTimer::RTCTimer(RTC& r, uint32_t clock) : rtc(r) { 12 | time = 0; 13 | setPeriod(clock); 14 | startTime = rtc.getTime(); 15 | } 16 | 17 | void RTCTimer::startTimer() { 18 | startTime = rtc.getTime(); 19 | bTimerStopped = false; 20 | } 21 | 22 | void RTCTimer::stopTimer() { 23 | time += rtc.getTime() - startTime; 24 | bTimerStopped = true; 25 | } 26 | 27 | void RTCTimer::reloadTimer() { 28 | time = 0; 29 | startTime = rtc.getTime(); 30 | bTimerStopped = false; 31 | } 32 | 33 | void RTCTimer::setPeriod(uint32_t clock) { 34 | clockPeriod = clock / 1000; 35 | } 36 | 37 | uint32_t RTCTimer::getTime() { 38 | return bTimerStopped ? time : time + rtc.getTime() - startTime; 39 | } 40 | 41 | bool RTCTimer::hasGoneOff() { 42 | return getTime() >= clockPeriod; 43 | } 44 | 45 | } // namespace core::dev 46 | -------------------------------------------------------------------------------- /include/core/io/CANDevice.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVT_CANDEVICE_HPP 2 | #define EVT_CANDEVICE_HPP 3 | 4 | #include "co_obj.h" 5 | 6 | /** 7 | * An abstract class used to define a class as a participant in the CAN Network. 8 | * Provides functions for getting the object dictionary, its size and the ID 9 | * of the CANDevice. These are used to initialize our CAN settings by just 10 | * passing a reference to the CANDevice subclass. 11 | */ 12 | class CANDevice { 13 | public: 14 | /** 15 | * Get a pointer to the object dictionary 16 | * 17 | * @return Pointer to the start of the object dictionary 18 | */ 19 | virtual CO_OBJ_T* getObjectDictionary() = 0; 20 | 21 | /** 22 | * Get the number of elements in the object dictionary. 23 | * 24 | * @return The number of elements in the object dictionary 25 | */ 26 | virtual uint8_t getNumElements() = 0; 27 | 28 | /** 29 | * Get the device's node ID 30 | * 31 | * @return The node ID of the can device. 32 | */ 33 | virtual uint8_t getNodeID() = 0; 34 | }; 35 | 36 | #endif // EVT_CANDEVICE_HPP 37 | -------------------------------------------------------------------------------- /samples/button_debounce/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace dev = core::dev; 8 | namespace io = core::io; 9 | namespace time = core::time; 10 | 11 | int main() { 12 | // Initialize system 13 | core::platform::init(); 14 | 15 | // Setup UART 16 | io::UART& uart = io::getUART(9600); 17 | io::GPIO& ledGPIO = io::getGPIO(); 18 | io::GPIO& buttonGPIO = io::getGPIO(); 19 | uint32_t debounceStart = time::millis(); 20 | 21 | dev::LED led(ledGPIO, dev::LED::ActiveState::HIGH); 22 | 23 | dev::Button button = dev::Button(buttonGPIO); 24 | 25 | uart.printf("Debounce Start: %d\n", debounceStart); 26 | 27 | while (1) { 28 | uart.printf("Tick: %d\n", time::millis()); 29 | if (button.debounce(300)) { 30 | uart.printf("Button Pressed\n"); 31 | led.toggle(); 32 | } 33 | 34 | time::wait(1000); 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /samples/blink/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example is the basic LED blink sample. This samples shows how the 3 | * device level drivers (the LED in this case) can be established by providing 4 | * the driver with the cooresponding IO level driver (GPIO in this case). 5 | * 6 | * The code will setup a GPIO pin as an output then setup an LED using that 7 | * GPIO. 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace io = core::io; 16 | namespace dev = core::dev; 17 | namespace time = core::time; 18 | 19 | int main() { 20 | // Initialize system 21 | core::platform::init(); 22 | 23 | // Setup the GPIO pin. 24 | // Notice that the pin used is called "LED". Each platform has a dedicated 25 | // LED pin, for the f3xx that is PB_13. 26 | io::GPIO& ledGPIO = io::getGPIO(); 27 | dev::LED led(ledGPIO, dev::LED::ActiveState::HIGH); 28 | 29 | while (1) { 30 | led.toggle(); 31 | 32 | // Wait half a second 33 | time::wait(500); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /include/core/dev/LED.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_LED_ 2 | #define _EVT_LED_ 3 | 4 | #include 5 | 6 | namespace core::dev { 7 | 8 | class LED { 9 | public: 10 | /** 11 | * Represents if the LED is active high or active low. 12 | */ 13 | enum class ActiveState { 14 | HIGH = 0u, 15 | LOW = 1u 16 | }; 17 | 18 | /** 19 | * Create an instance of the LED based on the given GPIO pin. 20 | * 21 | * @param[in] gpio GPIO pin 22 | * @param[in] activeState Represents if the LED is active high or active low 23 | */ 24 | LED(core::io::GPIO& gpio, ActiveState activeState); 25 | 26 | /** 27 | * Toggle the current state of the LED 28 | */ 29 | void toggle(); 30 | 31 | /** 32 | * Set the current state of the LED. 33 | * 34 | * @param[in] state The state to set the LED to. 35 | */ 36 | void setState(core::io::GPIO::State state); 37 | 38 | private: 39 | /// The gpio pin used by the LED 40 | core::io::GPIO& gpio; 41 | /// If the LED is active high or active low 42 | ActiveState activeState; 43 | }; 44 | 45 | } // namespace core::dev 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /cmake/evt-core_install.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | Macro to install and expose the library associated with the currently built project. 3 | ]] 4 | # 5 | macro(install_and_expose proj_name) 6 | # Expose headers 7 | target_include_directories(${proj_name} 8 | PUBLIC $ 9 | $ 10 | ) 11 | 12 | target_compile_definitions(${proj_name} PRIVATE -D_EXPORT) 13 | 14 | set_target_properties(${proj_name} PROPERTIES DEBUG_POSTFIX "d") 15 | 16 | install(TARGETS ${proj_name} 17 | EXPORT ${proj_name}-config 18 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 19 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 20 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 21 | ) 22 | 23 | install( 24 | EXPORT ${proj_name}-config 25 | NAMESPACE ${proj_name}:: 26 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${proj_name} 27 | ) 28 | 29 | install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ 30 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${proj_name} 31 | ) 32 | endmacro() 33 | -------------------------------------------------------------------------------- /samples/rtc/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example prints out the time as read in from the RTC 3 | * every second. 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | namespace io = core::io; 10 | namespace dev = core::dev; 11 | namespace time = core::time; 12 | 13 | int main() { 14 | core::platform::init(); 15 | 16 | io::UART& uart = io::getUART(9600); 17 | 18 | uart.printf("Starting RTC test\r\n"); 19 | 20 | // Start RTC and set the default time 21 | time::TimeStamp time; 22 | time.year = 24; 23 | time.month = 4; 24 | time.day = 8; 25 | 26 | time.hour = 19; 27 | time.minute = 23; 28 | time.second = 55; 29 | 30 | dev::RTC& rtc = dev::getRTC(); 31 | rtc.setTime(time); 32 | 33 | time::wait(500); 34 | 35 | uint32_t epochTime; 36 | 37 | while (1) { 38 | rtc.getTime(time); 39 | 40 | uart.printf("%d/%d/%d %d:%d:%d\r\n", time.day, time.month, time.year, time.hour, time.minute, time.second); 41 | 42 | epochTime = rtc.getTime(); 43 | uart.printf("Timestamp since Epoch: %d\r\n\r\n", epochTime); 44 | time::wait(1000); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /include/core/utils/time.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The functions defined in here are used for time based operations. All 3 | * operations are platform independent. 4 | */ 5 | 6 | #ifndef _EVT_TIME_ 7 | #define _EVT_TIME_ 8 | 9 | #include 10 | 11 | namespace core::time { 12 | /** 13 | * Function to have the program hold for a set amount of time before 14 | * continuing. 15 | * 16 | * @param ms The number of milliseconds to wait for 17 | */ 18 | void wait(uint32_t ms); 19 | 20 | /** 21 | * Get the milliseconds since system startup 22 | * 23 | * @return Time in milliseconds 24 | */ 25 | uint32_t millis(); 26 | 27 | /** 28 | * Struct representing a timestamp. 29 | */ 30 | struct TimeStamp { 31 | /** 32 | * The current year 33 | */ 34 | uint16_t year; 35 | /** 36 | * The current month (1-12) 37 | */ 38 | uint8_t month; 39 | /** 40 | * The current day (1-31) 41 | */ 42 | uint8_t day; 43 | /** 44 | * The hour in a 24 hour timeframe 45 | */ 46 | uint8_t hour; 47 | /** 48 | * The minute (0-59) 49 | */ 50 | uint8_t minute; 51 | /** 52 | * The second (0-59) 53 | */ 54 | uint8_t second; 55 | }; 56 | 57 | } // namespace core::time 58 | #endif 59 | -------------------------------------------------------------------------------- /src/core/io/UART.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace core::io { 7 | 8 | UART::UART(Pin txPin, Pin rxPin, uint32_t baudrate) { 9 | this->txPin = txPin; 10 | this->rxPin = rxPin; 11 | this->baudrate = baudrate; 12 | } 13 | 14 | UART::UART(const UART& uart) { 15 | txPin = uart.txPin; 16 | rxPin = uart.rxPin; 17 | baudrate = uart.baudrate; 18 | } 19 | 20 | char* UART::gets(char* buf, size_t size) { 21 | char ret = '\0'; 22 | size_t buf_index = 0; 23 | memset(buf, 0, size); 24 | 25 | while (ret != '\r' && ret != '\n' && ret != '\4') { // '\4' is EOF 26 | ret = getc(); 27 | 28 | // Check if backspace key is entered 29 | if (ret == '\b') { 30 | if (buf_index > 0 && buf_index < size) { 31 | buf[--buf_index] = '\0'; 32 | putc('\b'); 33 | putc(' '); 34 | putc('\b'); 35 | } 36 | } else if (buf_index < (size - 1) && ret != '\r' && ret != '\n' && ret != '\4') { 37 | buf[buf_index++] = ret; 38 | putc(ret); 39 | } 40 | } 41 | 42 | return buf; 43 | } 44 | 45 | } // namespace core::io 46 | -------------------------------------------------------------------------------- /.vscode/launch.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "stlinkgdbtarget", 5 | "request": "launch", 6 | "name": "Debug", 7 | "origin": "snippet", 8 | "cwd": "${workspaceFolder}", 9 | "preBuild": "${command:st-stm32-ide-debug-launch.build}", 10 | "runEntry": "main", 11 | "imagesAndSymbols": [ 12 | { 13 | "imageFileName": "${command:cmake.launchTargetPath}" 14 | } 15 | ], 16 | "faultUnalignedAccess": false 17 | }, 18 | { 19 | "type": "stlinkgdbtarget", 20 | "request": "launch", 21 | "name": "Select From Targets", 22 | "origin": "snippet", 23 | "cwd": "${workspaceFolder}", 24 | "preBuild": "${command:st-stm32-ide-debug-launch.build}", 25 | "runEntry": "main", 26 | "imagesAndSymbols": [ 27 | { 28 | "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}" //Provides a run prompt 29 | } 30 | ], 31 | "faultUnalignedAccess": false 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /cmake/evt-core_build.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | Creates an executable with the provided name. Generates bin, hex, elf, and map 3 | files for the given name. This will make a dedicated project. 4 | ]]# 5 | macro(make_exe proj_name sources) 6 | project(${proj_name} C CXX ASM) 7 | add_definitions(-DUSE_HAL_LIBRARY) 8 | 9 | add_executable(${proj_name} ${sources}) 10 | 11 | # Make the main executable have an ".elf" suffix 12 | set_target_properties(${proj_name} PROPERTIES 13 | OUTPUT_NAME "${proj_name}" 14 | SUFFIX ".elf" 15 | ) 16 | 17 | # Generate a map file 18 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \ 19 | -Wl,-Map=${proj_name}.map") 20 | set(HEX_FILE "${proj_name}.hex") 21 | set(BIN_FILE "${proj_name}.bin") 22 | add_custom_command(TARGET ${proj_name} POST_BUILD 23 | COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${HEX_FILE} 24 | COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${BIN_FILE} 25 | COMMENT "Building ${HEX_FILE} \nBuilding ${BIN_FILE}") 26 | 27 | target_link_libraries(${proj_name} PUBLIC EVT) 28 | 29 | if(USE_RTOS) 30 | target_link_libraries(${proj_name} PUBLIC threadx) 31 | endif() 32 | endmacro() 33 | -------------------------------------------------------------------------------- /samples/rtc_timer/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | namespace io = core::io; 7 | namespace dev = core::dev; 8 | 9 | int main() { 10 | core::platform::init(); 11 | 12 | io::UART& uart = io::getUART(9600); 13 | 14 | // Specific implementation of dev::RTC, clock type can vary 15 | dev::RTC& clock = dev::getRTC(); 16 | 17 | dev::RTCTimer timer(clock, 5000); 18 | 19 | uart.printf("\r\nTimer starting!\r\n"); 20 | uart.printf("Current time: %d\r\n", timer.getTime()); 21 | timer.startTimer(); 22 | uart.printf("Waiting...\r\n"); 23 | time::wait(1000); 24 | uart.printf("Stopped...\r\n"); 25 | timer.stopTimer(); 26 | uart.printf("Current time: %d\r\n", timer.getTime()); // should be same 27 | uart.printf("Waiting...\r\n"); 28 | time::wait(1000); 29 | uart.printf("Current time: %d\r\n", timer.getTime()); // should be same 30 | timer.startTimer(); 31 | 32 | while (1) { 33 | if (timer.hasGoneOff()) { 34 | uart.printf("Gone off!\r\n"); 35 | uart.printf("Current time: %d\r\n", timer.getTime()); 36 | timer.reloadTimer(); 37 | uart.printf("\r\nTimer starting!\r\n"); 38 | timer.startTimer(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /docs/source/_static/original/evt_core_layers.drawio: -------------------------------------------------------------------------------- 1 | 5ZnLUtswGIWfJktmrIsdZ0lDWjpAgVLosiMsOfZUtjyK0iQ8feVYduLIKXQaxVA2jHzk63cOvy4ZoHG2/CRJkVwJyvgAenQ5QGcDCH0M9N9SWFUCCkaVMJUprSSwEe7SJ2ZEz6jzlLJZ60QlBFdp0RYjkecsUi2NSCkW7dNiwdtPLciUWcJdRLitfk+pSio19L2Nfs7SaVI/GXimJyP1yUaYJYSKxZaEJgM0lkKoqpUtx4yX7Gou1XUf9/Q2LyZZrl5yAbv+Bifjp6/wNr6dX6wuv8Q/ghNzl1+Ez80HX43vzfuqVQ1BinlOWXkfb4A+LJJUsbuCRGXvQruutURlXB8B3YxTzseCC7m+FsVxDKNI6zMlxU+21UODx8APdI95ByYVW+79ONAg01FjImNKrvQp5gJUUzYxg6E5XmxMg9hoyZZhtUZMTqbNrTcodcPQ/Auy0CJ7fnp5WLJhxLrJPoY+9j1HZHHfZIFvobW46n+2omxGQuZMPo/WQhjCRxSU4ZRCEZWKXMsnICyhrmtb1SqZYM+2hvospPgwBmCvbQAIbAMabduA0JkBw2MasMaNj4YbBS/ADY+KO7Rwn00eLOL6k9WfmOYiZzvojER4Oi3zHWlEa69KgKkeA09NR5ZSWj6m08R2CTuEA6HfdmBoO9BVcKAzA0aWAZ+v/1/+ONyp+KBn/tCepfzbQLq/2LgsLPD5wtKF1VldgcjCesOJioXMXmm4t8fikaP5DRj1nXZs2XJaFFwjW3/6YYM/CoaIdASfAR39oSPCsO8ZJLQnMBds9UpDfwAHmgpeO9CxOjpuxu0R9Q0GG+4ujToGStCBFbjCijwL6/1M56/cHqHMQb45i1X/6cY7Nni+ZUPX+shZupFdwd/gfMVKN+o73fa6f/Lw7USvMN9PtGHf0Q5cR7vZu9q32+Ui2n7f0bbHQySpFm6IVC4mJq8z3bjndGN7/Dxwups973275C7S3bF/ctR0Y3v9fk4kXZB3VLgDZ9HWh5sfkdZ9W7/Eoclv -------------------------------------------------------------------------------- /samples/i2c/arduino_source/i2c_slave_example/i2c_slave_example.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * file: i2c_slave.ino 3 | * purpose: Slave code that goes with the test_i2c.cpp code. 4 | * This code is meant to run on an Arduino. 5 | */ 6 | 7 | #include 8 | 9 | void receive_handler(int count); 10 | void request_handler(); 11 | 12 | char response_buf[] = "o"; 13 | 14 | void setup() 15 | { 16 | Wire.begin(4); // Join the I2C bus with an address of 4 17 | Wire.onReceive(receive_handler); // Register the receive handler 18 | Wire.onRequest(request_handler); // Register the request handler 19 | Serial.begin(9600); // Start serial communications for debugging 20 | Serial.println("I2C test..."); 21 | } 22 | 23 | void loop() 24 | { 25 | delay(50); // We're waiting for events so do nothing here. 26 | } 27 | 28 | void receive_handler(int count) 29 | { 30 | char temp; 31 | while (Wire.available()) // While there are chars to read 32 | { 33 | temp = Wire.read(); // Read a char 34 | if(temp == 0) 35 | response_buf[0] = 'o'; 36 | else 37 | response_buf[0] = 'k'; 38 | } 39 | Serial.println(); // Move to the next line 40 | } 41 | 42 | void request_handler() 43 | { 44 | Wire.write(response_buf); // Respond with the message expected by the master. 45 | } 46 | -------------------------------------------------------------------------------- /samples/thermistor/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example prints out temperature reading from a thermistor 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace io = core::io; 11 | namespace dev = core::dev; 12 | namespace time = core::time; 13 | 14 | /** 15 | * Note, this conversion function is just to show off how a conversion 16 | * function will look like. In actuality, this will be determined through 17 | * testing/reading the thermistor datasheet. 18 | */ 19 | uint32_t convert(uint32_t voltage) { 20 | return voltage / 2; 21 | } 22 | 23 | int main() { 24 | core::platform::init(); 25 | 26 | // Setup IO 27 | io::UART& uart = io::getUART(9600); 28 | 29 | time::wait(500); 30 | 31 | io::ADC& adc = io::getADC(); 32 | 33 | time::wait(500); 34 | 35 | // Setup the thermistor device 36 | dev::Thermistor thermistor(adc, convert); 37 | 38 | uart.printf("Starting thermistor test\r\n"); 39 | 40 | while (1) { 41 | uart.printf("Temperature: %dmC\r\n", static_cast(thermistor.getTempCelcius())); 42 | uart.printf("Voltage: %dV\r\n", static_cast(thermistor.getRawADC())); 43 | time::wait(100); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /include/core/dev/Thermistor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_THERMISTOR_ 2 | #define _EVT_THERMISTOR_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace core::dev { 9 | 10 | /** 11 | * Handles representing any device that can produce temperature reading based 12 | * on incoming ADC values. 13 | */ 14 | class Thermistor { 15 | public: 16 | /** 17 | * Create a new thermistor which will use the provided ADC and 18 | * pass those values through the conversion to produce a temperature 19 | * reading. 20 | * 21 | * @param[in] adc The ADC to use to convert ADC values into temperature 22 | * @param[in] conversion The conversion function 23 | */ 24 | Thermistor(core::io::ADC& adc, uint32_t (*conversion)(uint32_t)); 25 | 26 | /** 27 | * Return the temperature in milli celcius of the thermistor 28 | * 29 | * @return The conversion of the ADC value into temperature 30 | */ 31 | uint32_t getTempCelcius(); 32 | 33 | /** 34 | * Returns the raw ADC values 35 | * 36 | * @return The raw values from the ADC 37 | */ 38 | uint32_t getRawADC(); 39 | 40 | private: 41 | /// The ADC interface to read from 42 | core::io::ADC& adc; 43 | /// Funtion that converts raw ADC values into milli Celcius 44 | uint32_t (*conversion)(uint32_t); 45 | }; 46 | 47 | } // namespace core::dev 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/core/io/ADC.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_ADC_ 2 | #define _EVT_ADC_ 3 | 4 | #include 5 | 6 | namespace core::io { 7 | 8 | // Forward declarations: 9 | // The different pins are hardware specific. Forward declarations to allow 10 | // at compilation time the decision of which pins should be used. 11 | enum class Pin; 12 | enum class ADCPeriph; 13 | 14 | class ADC { 15 | 16 | public: 17 | /** 18 | * Setup the given pin for ADC (analog to digital) usage 19 | * 20 | * @param[in] pin The pin to setup for ADC 21 | */ 22 | ADC(Pin pin, ADCPeriph adcPeriph); 23 | 24 | /** 25 | * Reads the current voltage in volts on the ADC 26 | * 27 | * @return The voltage in volts 28 | */ 29 | virtual float read() = 0; 30 | 31 | /** 32 | * Read the raw value from the ADC 33 | * 34 | * @return The raw value from the ADC 35 | */ 36 | virtual uint32_t readRaw() = 0; 37 | 38 | /** 39 | * Read the value from the ADC as a percentage of the possible values 40 | * from 0 to 1 This is based on the maximum possible valie the ADC 41 | * can read. 42 | * 43 | * @return The ADC value as a percentage 44 | */ 45 | virtual float readPercentage() = 0; 46 | 47 | protected: 48 | /// The pin the ADC is attached to 49 | Pin pin; 50 | /// The internal ADC being used 51 | ADCPeriph adcPeriph; 52 | }; 53 | 54 | } // namespace core::io 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/core/io/platform/f4xx/UARTf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_UARTf4xx_ 2 | #define _EVT_UARTf4xx_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace core::io { 9 | 10 | class UARTf4xx : public UART { 11 | public: 12 | /** 13 | * Create an instance of the STMF302x8 UART interface using the provided 14 | * TX and RX pins. 15 | * 16 | * @param[in] txPin The UART TX pin. 17 | * @param[in] rxPin THe UART RX pin. 18 | * @param[in] baudrate The baudrate to operate the UART with/ 19 | */ 20 | UARTf4xx(Pin txPin, Pin rxPin, uint32_t baudrate, bool isSwapped); 21 | 22 | void setBaudrate(uint32_t baudrate); 23 | 24 | void setFormat(WordLength wordLength = WordLength::EIGHT, Parity parity = Parity::NONE, 25 | NumStopBits numStopBits = NumStopBits::ONE); 26 | 27 | void sendBreak(); 28 | 29 | bool isReadable(); 30 | 31 | bool isWritable(); 32 | 33 | void putc(char c); 34 | 35 | void puts(const char* s); 36 | 37 | char getc(); 38 | 39 | void printf(const char* format, ...); 40 | 41 | void write(uint8_t byte); 42 | 43 | uint8_t read(); 44 | 45 | void writeBytes(uint8_t* bytes, size_t size); 46 | 47 | void readBytes(uint8_t* bytes, size_t size); 48 | 49 | private: 50 | /// HAL representation of the UART 51 | UART_HandleTypeDef halUART; 52 | }; 53 | } // namespace core::io 54 | #endif 55 | -------------------------------------------------------------------------------- /include/core/dev/button.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_BUTTON_ 2 | #define _EVT_BUTTON_ 3 | 4 | #include 5 | #include 6 | 7 | namespace core::dev { 8 | // Forward declarations: 9 | // The different pins are hardware specific. Forward declaration to allow 10 | // at compilation time the decision of which pins should be used. 11 | 12 | class Button { 13 | public: 14 | /** 15 | * Create an instance of the Button based on the given GPIO pin. 16 | * 17 | * @param gpio[in] GPIO pin 18 | * @param pressedState[in] Which GPIO state indicates the button is pressed 19 | */ 20 | Button(io::GPIO& gpio, io::GPIO::State pressedState = io::GPIO::State::HIGH); 21 | 22 | /** 23 | * Gets the button's GPIO Pin state 24 | * 25 | * @return The state of the pin 26 | */ 27 | io::GPIO::State getState(); 28 | 29 | /** 30 | * Confirms a button press based on a user defined debounce time 31 | * 32 | * @param debounceTime 33 | * @return Confirmation of a button press 34 | */ 35 | bool debounce(uint32_t debounceTime); 36 | 37 | private: 38 | /** The GPIO pin that the button is connected to */ 39 | io::GPIO& gpio; 40 | 41 | /** The time since the button was last pressed */ 42 | uint32_t timeSinceLastPress; 43 | 44 | /** The GPIO state that means the button is being pressed */ 45 | io::GPIO::State pressedState; 46 | }; 47 | 48 | } // namespace core::dev 49 | #endif 50 | -------------------------------------------------------------------------------- /samples/log/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example that logs sample statements with some sample data. 3 | * 4 | * The sample will log only the info, warning, and error statements because the 5 | * logger's level has been set to info. 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace io = core::io; 14 | namespace log = core::log; 15 | namespace dev = core::dev; 16 | 17 | int main() { 18 | // Initialize system 19 | core::platform::init(); 20 | 21 | io::UART& uart = io::getUART(9600); 22 | 23 | // Print directly to the UART to show that the file has been run despite any 24 | // problems with the Logger 25 | uart.printf("Starting log test\n\r"); 26 | 27 | // Set up the logger with a UART, logLevel, and clock 28 | // If timestamps aren't needed, don't set the logger's clock 29 | log::LOGGER.setUART(&uart); 30 | log::LOGGER.setLogLevel(log::Logger::LogLevel::INFO); 31 | dev::RTC& rtc = dev::getRTC(); 32 | log::LOGGER.setClock(&rtc); 33 | 34 | uint8_t sampleData = 0xab; 35 | 36 | // Attempt to log a statement at each log level 37 | log::LOGGER.log(log::Logger::LogLevel::DEBUG, "Log 0"); 38 | log::LOGGER.log(log::Logger::LogLevel::INFO, "Log 1"); 39 | log::LOGGER.log(log::Logger::LogLevel::WARNING, "Log 2 - %x", sampleData); 40 | log::LOGGER.log(log::Logger::LogLevel::ERROR, "Log 3 - %d", sampleData); 41 | } 42 | -------------------------------------------------------------------------------- /samples/gpio_interrupt/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a basic sample of using the UART module. The program provides a 3 | * basic echo functionality where the uart will write back whatever the user 4 | * enters. 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | namespace io = core::io; 11 | 12 | constexpr int BAUD_RATE = 9600; 13 | constexpr io::Pin INTERRUPT_PIN = io::Pin::PC_3; 14 | 15 | io::UART* uart; 16 | 17 | void risingEdgeHandler(io::GPIO* pin, void* priv) { 18 | // we don't need the void* in this handler, but the registerIRQ() 19 | // method requires a function with these exact arguments 20 | io::GPIO::State pin_value = pin->readPin(); 21 | 22 | uart->printf("Received %s edge interrupt for pin C3\n\r", 23 | pin_value == io::GPIO::State::HIGH ? "rising" : "falling"); 24 | uart->printf("Pin Value: %d\n\r", static_cast(pin_value)); 25 | } 26 | 27 | int main() { 28 | // Initialize system 29 | core::platform::init(); 30 | 31 | // Setup UART 32 | uart = &io::getUART(BAUD_RATE); 33 | 34 | // Set the GPIO interrupt 35 | io::GPIO& interruptGPIO = io::getGPIO(io::GPIO::Direction::INPUT); 36 | interruptGPIO.registerIRQ(io::GPIO::TriggerEdge::RISING_FALLING, risingEdgeHandler, nullptr); 37 | 38 | uart->printf("\n\rWaiting for interrupts...\n\r"); 39 | 40 | while (1) { 41 | continue; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/source/glossary.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Glossary 3 | ======== 4 | 5 | This contains definitions for common acronyms, phrases, or other words that 6 | are helpful to under stand. Some are clarifications on terms that are used 7 | in a specific way by EVT. 8 | 9 | ============= =========================== ====================== 10 | Term Definition More Info 11 | ------------- --------------------------- ---------------------- 12 | CAN Controller Area Network `CAN `_ 13 | Board The PCB being developed for 14 | EVT Electric Vehicle Team 15 | EVT-core The main libary for EVT 16 | firmware development. 17 | I2C Inter-Integrated Circuit `I2C `_ 18 | MCU Microcontroller `MCU `_ 19 | Platform The MCU running the code 20 | PWM Pulse Width Modulation `PWM `_ 21 | SPI Serial Peripheral Interface `SPI `_ 22 | Target The executable 23 | UART Universal asynchronous `UART `_ 24 | receiver-transmitter 25 | ============= =========================== ====================== 26 | -------------------------------------------------------------------------------- /include/core/dev/Timer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVT_TIMER_HPP 2 | #define EVT_TIMER_HPP 3 | 4 | #include 5 | 6 | namespace core::dev { 7 | 8 | /** 9 | * This class will represent an internal general purpose timer device for the STM32. 10 | * It is capable of triggering interrupts with a given frequency 11 | */ 12 | class Timer { 13 | public: 14 | /** 15 | * Starts the given timer and registers the given interrupt pointer to trigger when the timer overflows 16 | * @param[in] irqHandler The IRQ Handler function pointer. Sets a new interrupt handler function 17 | */ 18 | virtual void startTimer(void (*irqHandler)(void* htim)) = 0; 19 | 20 | /** 21 | * Starts the given timer using the IRQ Handler already assigned to that timer. 22 | */ 23 | virtual void startTimer() = 0; 24 | 25 | /** 26 | * Stops the current timer from running. Does not complete its current counting sequence. 27 | */ 28 | virtual void stopTimer() = 0; 29 | 30 | /** 31 | * Resets the timer counter. 32 | */ 33 | virtual void reloadTimer() = 0; 34 | 35 | /** 36 | * Set the clock period for the timer. Will stop the timer, re-initialize the device with the updated period. 37 | * You must call startTimer again to continue timer operation. 38 | * 39 | * @param[in] clockPeriod the clock period in ms. An interrupt will be triggered at that frequency. 40 | */ 41 | virtual void setPeriod(uint32_t clockPeriod) = 0; 42 | }; 43 | 44 | } // namespace core::dev 45 | 46 | #endif // EVT_TIMER_HPP 47 | -------------------------------------------------------------------------------- /samples/adc/single_adc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example shows off the use of the ADC. Two pins are setup for ADC 3 | * functionality and the values are continuously read in and printed over 4 | * UART. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace io = core::io; 13 | namespace time = core::time; 14 | 15 | int main() { 16 | // Initialize system 17 | core::platform::init(); 18 | 19 | io::UART& uart = io::getUART(9600); 20 | 21 | // Set up the logger to catch errors in ADC creation 22 | core::log::LOGGER.setUART(&uart); 23 | core::log::LOGGER.setLogLevel(core::log::Logger::LogLevel::INFO); 24 | 25 | uart.printf("Starting ADC test\r\n"); 26 | 27 | time::wait(500); 28 | 29 | io::ADC& adc0 = io::getADC(); 30 | 31 | while (1) { 32 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------"); 33 | core::log::LOGGER.log( 34 | core::log::Logger::LogLevel::INFO, "ADC0 : %d mV", static_cast(adc0.read() * 1000)); 35 | core::log::LOGGER.log( 36 | core::log::Logger::LogLevel::INFO, "ADC0: %d%%", static_cast(adc0.readPercentage() * 100)); 37 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "ADC0 raw: %d", adc0.readRaw()); 38 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------\r\n"); 39 | time::wait(500); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /include/core/io/platform/f3xx/UARTf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_UARTf3xx_ 2 | #define _EVT_UARTf3xx_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace core::io { 11 | 12 | class UARTf3xx : public UART { 13 | public: 14 | /** 15 | * Create an instance of the STMF3xx UART interface using the provided 16 | * TX and RX pins. 17 | * 18 | * @param[in] txPin The UART TX pin. 19 | * @param[in] rxPin THe UART RX pin. 20 | * @param[in] baudrate The baudrate to operate the UART with 21 | * @param[in] isSwapped Whether TX and RX should be swapped 22 | */ 23 | UARTf3xx(Pin txPin, Pin rxPin, uint32_t baudrate, bool isSwapped); 24 | void setBaudrate(uint32_t baudrate) override; 25 | void setFormat(WordLength wordLength = WordLength::EIGHT, Parity parity = Parity::NONE, 26 | NumStopBits numStopBits = NumStopBits::ONE) override; 27 | 28 | void sendBreak() override; 29 | 30 | bool isReadable() override; 31 | bool isWritable() override; 32 | 33 | void putc(char c) override; 34 | void puts(const char* s) override; 35 | char getc() override; 36 | 37 | void printf(const char* format, ...) override; 38 | 39 | void write(uint8_t byte) override; 40 | uint8_t read() override; 41 | 42 | void writeBytes(uint8_t* bytes, size_t size) override; 43 | void readBytes(uint8_t* bytes, size_t size) override; 44 | 45 | private: 46 | /// HAL representation of the UART 47 | UART_HandleTypeDef halUART; 48 | }; 49 | 50 | } // namespace core::io 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/core/io/PWM.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_PWM_ 2 | #define _EVT_PWM_ 3 | 4 | #include 5 | 6 | namespace core::io { 7 | 8 | // Forward declarations: 9 | // The diferent pins are hardware specific. Forward declarations to allow 10 | // at compilation time the decision of which pins should be used. 11 | enum class Pin; 12 | 13 | class PWM { 14 | 15 | public: 16 | /** 17 | * Setup the given pin for PWM usage. 18 | * 19 | * @param[in] pin The pin to setup for PWM 20 | */ 21 | PWM(Pin pin); 22 | 23 | /** 24 | * Set the duty cycle for the pin to operate at. 25 | * 26 | * @param[in] dutyCycle Duty cycle as a whole number to set the pin to. 27 | */ 28 | virtual void setDutyCycle(uint32_t dutyCycle) = 0; 29 | 30 | /** 31 | * Set the period for the PWM in microseconds. 32 | * 33 | * @param[in] period The period of the PWM in microseconds. 34 | */ 35 | virtual void setPeriod(uint32_t period) = 0; 36 | 37 | /** 38 | * Get the current duty cycle. 39 | * 40 | * @return The duty cycle the PWM is operating at. 41 | */ 42 | virtual uint32_t getDutyCycle() = 0; 43 | 44 | /** 45 | * Get the current period. 46 | * 47 | * @return The period the PWM is operating at in microseconds. 48 | */ 49 | virtual uint32_t getPeriod() = 0; 50 | 51 | protected: 52 | /// The pin the PWM is attached to 53 | Pin pin; 54 | /// The duty cycle of the PWM 55 | uint32_t dutyCycle; 56 | /// The period of the PWM 57 | uint32_t period; 58 | }; 59 | 60 | } // namespace core::io 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /samples/canopen/canopen_tpdo/arduino_receive/arduino_receive.ino: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include 5 | 6 | //#define CS_PIN 9 //CAN shield v2 7 | #define CS_PIN 10 //CAN shield v1.4 8 | #define IRQ_PIN 2 9 | 10 | void onReceive(int packetSize) { 11 | // received a packet 12 | Serial.print("Received "); 13 | 14 | if (CAN.packetExtended()) { 15 | Serial.print("extended "); 16 | } 17 | 18 | if (CAN.packetRtr()) { 19 | // Remote transmission request, packet contains no data 20 | Serial.print("RTR "); 21 | } 22 | 23 | Serial.print("packet with id 0x"); 24 | Serial.print(CAN.packetId(), HEX); 25 | 26 | if (CAN.packetRtr()) { 27 | Serial.print(" and requested length "); 28 | Serial.println(CAN.packetDlc()); 29 | } else { 30 | Serial.print(" and length "); 31 | Serial.println(packetSize); 32 | 33 | // only print packet data for non-RTR packets 34 | while (CAN.available()) { 35 | Serial.print(" "); 36 | Serial.print(CAN.read(), HEX); 37 | } 38 | Serial.println(); 39 | } 40 | 41 | Serial.println(); 42 | } 43 | 44 | void setup() { 45 | Serial.begin(9600); 46 | while (!Serial); 47 | 48 | Serial.println("CAN Receiver"); 49 | 50 | CAN.setPins(CS_PIN, IRQ_PIN); 51 | // start the CAN bus at 500 kbps 52 | if (!CAN.begin(500E3)) { 53 | Serial.println("Starting CAN failed!"); 54 | while (1); 55 | } 56 | 57 | // register the receive callback 58 | CAN.onReceive(onReceive); 59 | } 60 | 61 | void loop() { 62 | delay(5); 63 | } 64 | -------------------------------------------------------------------------------- /src/core/io/types/CANMessage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace core::io { 7 | 8 | CANMessage::CANMessage(uint32_t id, uint8_t dataLength, uint8_t* payload, bool isExtended) { 9 | this->id = id; 10 | // TODO: Should include way to notify user of invalid CAN frame, 11 | // to be added to error manager later. 12 | this->dataLength = dataLength <= CAN_MAX_PAYLOAD_SIZE ? dataLength : CAN_MAX_PAYLOAD_SIZE; 13 | 14 | // Copy contents of provided payload into message's payload 15 | for (int i = 0; i < this->dataLength; i++) 16 | this->payload[i] = payload[i]; 17 | 18 | this->isExtended = isExtended; 19 | } 20 | 21 | CANMessage::CANMessage() { 22 | this->id = 0; 23 | this->dataLength = 0; 24 | } 25 | 26 | uint32_t CANMessage::getId() { 27 | return id; 28 | } 29 | 30 | uint8_t CANMessage::getDataLength() { 31 | return dataLength; 32 | } 33 | 34 | uint8_t* CANMessage::getPayload() { 35 | return &payload[0]; 36 | } 37 | 38 | void CANMessage::setId(uint32_t id) { 39 | this->id = id; 40 | } 41 | 42 | void CANMessage::setDataLength(uint8_t size) { 43 | this->dataLength = size; 44 | } 45 | 46 | void CANMessage::setPayload(const uint8_t* payload) { 47 | std::memcpy(this->payload, payload, CAN_MAX_PAYLOAD_SIZE); 48 | } 49 | 50 | CANMessage& CANMessage::operator=(const CANMessage& other) { 51 | this->id = other.id; 52 | this->dataLength = other.dataLength; 53 | this->setPayload(other.payload); 54 | return *this; 55 | } 56 | 57 | bool CANMessage::isCANExtended() { 58 | return this->isExtended; 59 | } 60 | 61 | } // namespace core::io 62 | -------------------------------------------------------------------------------- /samples/lcd/lcd-alphabet/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample code for displaying the Alphabet on an LCD. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace dev = core::dev; 11 | namespace io = core::io; 12 | namespace time = core::time; 13 | 14 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; 15 | 16 | constexpr uint8_t deviceCount = 1; 17 | 18 | io::GPIO* devices[deviceCount]; 19 | 20 | int main() { 21 | // Initialize system 22 | core::platform::init(); 23 | 24 | // Setup UART 25 | io::UART& uart = io::getUART(9600); 26 | 27 | // Uses HUDL 1.0 Pins 28 | io::GPIO& regSelect = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 29 | io::GPIO& reset = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 30 | 31 | devices[0] = &io::getGPIO(core::io::GPIO::Direction::OUTPUT); 32 | devices[0]->writePin(io::GPIO::State::HIGH); 33 | 34 | // Setup SPI 35 | io::SPI& spi = io::getSPI(devices, deviceCount); 36 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE0, SPI_MSB_FIRST); 37 | 38 | // Sets up LCD 39 | uart.printf("Creating LCD Object...\n\r"); 40 | core::dev::LCD lcd(regSelect, reset, spi); 41 | uart.printf("Initializing LCD...\n\r"); 42 | lcd.initLCD(); 43 | lcd.clearLCD(); 44 | 45 | const char* text = 46 | R"( !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~)"; 47 | lcd.writeText(text, 0, 0, core::dev::LCD::SMALL, true); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /libs/HALf4/include/HALf4/stm32f4xx_it.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f4xx_it.h 4 | * @author MCD Application Team 5 | * @brief This file contains the headers of the interrupt handlers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2017 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef __STM32F4xx_IT_H 21 | #define __STM32F4xx_IT_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | #include "stm32f4xx_hal.h" 29 | 30 | /* Exported types ------------------------------------------------------------*/ 31 | /* Exported constants --------------------------------------------------------*/ 32 | /* Exported macro ------------------------------------------------------------*/ 33 | /* Exported functions ------------------------------------------------------- */ 34 | 35 | void NMI_Handler(void); 36 | void HardFault_Handler(void); 37 | void MemManage_Handler(void); 38 | void BusFault_Handler(void); 39 | void UsageFault_Handler(void); 40 | void DebugMon_Handler(void); 41 | void SysTick_Handler(void); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* __STM32F4xx_IT_H */ -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | Contains notable changes there were added, fixed, or removed in each release. 4 | 5 | ## 1.0.0 6 | 7 | ### Added 8 | 9 | * Support for the STM32f334 10 | * ADC 11 | * CAN 12 | * GPIO 13 | * I2C 14 | * PWM 15 | * SPI 16 | * Timer 17 | * UART 18 | * Watchdog 19 | * Support for the STM32F302r8 20 | * SPI 21 | * Timer 22 | * CANopen Support via canopen-stack 23 | * Logging 24 | * Style linting 25 | * Device Drivers 26 | * EEPROM 27 | * M24C32 28 | * Watchdog 29 | * STM internal IWDG 30 | * Button 31 | * Thermistor 32 | * CAN ID Message Filtering 33 | 34 | ### Fixed 35 | 36 | * CAN hardfault handler associated with TX queue 37 | * Linker flags to Remove Un-Used Code 38 | * Multi-Channel ADC Support 39 | 40 | ### Changed 41 | 42 | * Error Handling/IO Status 43 | * I2C status return value 44 | * CAN status return value 45 | * Standardize GPIO Initialization Logic 46 | * Fixed Point PWM 47 | * Option for Internal GPIO Resistor Direction 48 | 49 | ## 0.2.0 50 | 51 | ### Added 52 | 53 | * RTC Support for the STM32F302r8 54 | * Improved Windows build support 55 | * GPIO Interrupt Support for the STM32F302r8 56 | * Sample for back-and-forth CAN communication 57 | * Documentation auto-generation 58 | 59 | ### Fixed 60 | 61 | * UART TX/RX bug due to differences in clock settings 62 | 63 | ### Changed 64 | 65 | * Relax line length style requirements to 100 characters 66 | 67 | ## 0.1.0 68 | 69 | ### Added 70 | 71 | * I2C Support for the STM32F302r8 72 | * PWM Support for the STM32F302r8 73 | * UART Support for the STM32F302r8 74 | * CAN Support for the STM32F302r8 75 | * GPIO Support for the STM32F302r8 76 | * Basic System Intialization for the STM32F302r8 77 | * Ability to build as library 78 | -------------------------------------------------------------------------------- /libs/HALf4/include/HALf4/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.2 5 | * @date 19. April 2017 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2017 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /samples/encoder/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example demonstrates how to utilize the encoder object, 3 | * Two pins are used to read the encoder values via interrupts 4 | * Static wrappers are necessary for the encoder to handle the pin interrupts 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace io = core::io; 15 | namespace dev = core::dev; 16 | namespace time = core::time; 17 | namespace log = core::log; 18 | 19 | constexpr io::Pin A_PIN = io::Pin::PA_8; 20 | constexpr io::Pin B_PIN = io::Pin::PA_9; 21 | 22 | int main() { 23 | // Init platform 24 | core::platform::init(); 25 | io::UART& uart = io::getUART(9600, true); 26 | 27 | uart.printf("\n\rSTARTING ENCODER TEST\n\r"); 28 | 29 | // init logger 30 | log::LOGGER.setUART(&uart); 31 | log::LOGGER.setLogLevel(log::Logger::LogLevel::DEBUG); 32 | 33 | io::GPIO& pinA = io::getGPIO(io::GPIO::Direction::INPUT); 34 | io::GPIO& pinB = io::getGPIO(io::GPIO::Direction::INPUT); 35 | 36 | dev::Encoder encoder(pinA, pinB, 18, 0, true); 37 | 38 | while (1) { 39 | // ENCODER MUST BE UPDATED EACH LOOP 40 | // Read the position of the encoder, which for this example will be in the range [0, 18] 41 | uint64_t position = encoder.getPosition(); 42 | 43 | // PRINT VALUES (only enable one at a time) 44 | // uart.printf("\r Encoder Change: %d ", change); 45 | uart.printf("\rPosition: %d ", position); 46 | 47 | // The wait simulates a loop that is doing other processing, because that will affect how often the output is 48 | // read 49 | time::wait(1000); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /include/core/dev/platform/f4xx/Timerf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_TIMER4xx_H 2 | #define _EVT_TIMER4xx_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace core::dev { 11 | 12 | /** 13 | * Implementation of the Timer class for STM32f4xx MCUs 14 | */ 15 | class Timerf4xx : public Timer { 16 | public: 17 | /** 18 | * Will initialize the timer device on the STM with the given period and the given IRQ Handler 19 | * that triggers with the given period. 20 | * @param timerPeripheral[in] The timer peripheral to configure. It is up to the user to verify 21 | * that resource conflicts do not occur. 22 | * 23 | * @param[in] timerPeripheral The timer to use 24 | * @param[in] clockPeriod the clock period in ms. An interrupt will be triggered at that frequency. 25 | */ 26 | explicit Timerf4xx(TIM_TypeDef* timerPeripheral, uint32_t clockPeriod); 27 | 28 | void startTimer(void (*irqHandler)(void* htim)) override; 29 | 30 | void startTimer() override; 31 | 32 | void stopTimer() override; 33 | 34 | void reloadTimer() override; 35 | 36 | void setPeriod(uint32_t clockPeriod) override; 37 | 38 | private: 39 | // Pointer to the halTimer struct stored in the global array in Timerf4xx.cpp 40 | TIM_HandleTypeDef* halTimer; 41 | 42 | // Timer clock period 43 | uint32_t clockPeriod; 44 | 45 | /** 46 | * Handles the initialization of the timer module. Actually configures the device and enables it. 47 | * @param[in] timerPeripheral The timer peripheral to configure. 48 | * @param[in] clockPeriod the clock period in ms. An interrupt will be triggered at that frequency. 49 | */ 50 | void initTimer(TIM_TypeDef* timerPeripheral, uint32_t clockPeriod); 51 | }; 52 | 53 | } // namespace core::dev 54 | 55 | #endif //_EVT_TIMER4xx_H 56 | -------------------------------------------------------------------------------- /libs/HALf3/include/HALf3/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.2 5 | * @date 19. April 2017 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2017 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /samples/lcd/lcd-counter/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample code for displaying a counting number on the LCD display. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace dev = core::dev; 13 | namespace io = core::io; 14 | namespace time = core::time; 15 | 16 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; 17 | 18 | constexpr uint8_t deviceCount = 1; 19 | 20 | io::GPIO* devices[deviceCount]; 21 | 22 | int main() { 23 | // Initialize system 24 | core::platform::init(); 25 | 26 | // Setup UART 27 | io::UART& uart = io::getUART(9600); 28 | 29 | // Uses HUDL 1.0 Pins 30 | io::GPIO& regSelect = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 31 | io::GPIO& reset = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 32 | 33 | devices[0] = &io::getGPIO(core::io::GPIO::Direction::OUTPUT); 34 | devices[0]->writePin(io::GPIO::State::HIGH); 35 | 36 | // Setup SPI 37 | io::SPI& spi = io::getSPI(devices, deviceCount); 38 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE0, SPI_MSB_FIRST); 39 | 40 | // Sets up LCD 41 | uart.printf("Creating LCD Object...\n\r"); 42 | core::dev::LCD lcd(regSelect, reset, spi); 43 | uart.printf("Initializing LCD...\n\r"); 44 | lcd.initLCD(); 45 | lcd.clearLCD(); 46 | 47 | uint8_t number = 0; 48 | 49 | while (true) { 50 | lcd.clearArea(64, 1, 7, 0); 51 | char buffer[128] = {}; 52 | snprintf(buffer, (8), "%d", (number)); 53 | 54 | lcd.writeText(buffer, 7, 0, core::dev::LCD::SMALL, true); 55 | 56 | number++; 57 | time::wait(500); 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /samples/can/back_and_forth/arduino_can/arduino_can.ino: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include 5 | 6 | bool readyToSend = true; 7 | 8 | void onReceive(int packetSize) { 9 | // received a packet 10 | Serial.print("Received "); 11 | 12 | if (CAN.packetExtended()) { 13 | Serial.print("extended "); 14 | } 15 | 16 | if (CAN.packetRtr()) { 17 | // Remote transmission request, packet contains no data 18 | Serial.print("RTR "); 19 | } 20 | 21 | Serial.print("packet with id 0x"); 22 | Serial.print(CAN.packetId(), HEX); 23 | 24 | if (CAN.packetRtr()) { 25 | Serial.print(" and requested length "); 26 | Serial.println(CAN.packetDlc()); 27 | } else { 28 | Serial.print(" and length "); 29 | Serial.println(packetSize); 30 | 31 | // only print packet data for non-RTR packets 32 | while (CAN.available()) { 33 | Serial.print(" "); 34 | Serial.print(CAN.read(), HEX); 35 | } 36 | Serial.println(); 37 | } 38 | 39 | Serial.println(); 40 | 41 | readyToSend = true; 42 | } 43 | 44 | void setup() { 45 | Serial.begin(9600); 46 | while (!Serial); 47 | 48 | Serial.println("CAN Sender"); 49 | 50 | // start the CAN bus at 500 kbps 51 | if (!CAN.begin(500E3)) { 52 | Serial.println("Starting CAN failed!"); 53 | while (1); 54 | } 55 | 56 | // register the receive callback 57 | CAN.onReceive(onReceive); 58 | } 59 | 60 | void loop() { 61 | 62 | while(!readyToSend) { 63 | delay(5); 64 | } 65 | Serial.print("Sending CAN message "); 66 | 67 | CAN.beginExtendedPacket(0xabcdef); 68 | CAN.write(0x01); 69 | CAN.write(0x02); 70 | CAN.write(0x03); 71 | CAN.write(0x04); 72 | CAN.write(0x05); 73 | CAN.endPacket(); 74 | 75 | readyToSend = false; 76 | 77 | Serial.println("done"); 78 | } 79 | -------------------------------------------------------------------------------- /src/core/io/I2C.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::io { 4 | 5 | I2C::I2C(Pin sclPin, Pin sdaPin) : sclPin(sclPin), sdaPin(sdaPin) {} 6 | 7 | I2C::I2CStatus I2C::write(uint8_t addr, uint8_t* bytes, uint8_t length) { 8 | for (int i = 0; i < length; i++) 9 | I2C_RETURN_IF_ERR(write(addr, bytes[i])); 10 | return I2C::I2CStatus::OK; 11 | } 12 | 13 | I2C::I2CStatus I2C::read(uint8_t addr, uint8_t* bytes, uint8_t length) { 14 | for (int i = 0; i < length; i++) 15 | I2C_RETURN_IF_ERR(read(addr, &bytes[i])); 16 | return I2C::I2CStatus::OK; 17 | } 18 | 19 | I2C::I2CStatus I2C::writeReg(uint8_t addr, uint8_t reg, uint8_t byte) { 20 | 21 | I2C_RETURN_IF_ERR(write(addr, reg)); 22 | I2C_RETURN_IF_ERR(write(addr, byte)); 23 | 24 | return I2C::I2CStatus::OK; 25 | } 26 | 27 | /** 28 | * Reading a register usually involves writing out a byte then reading 29 | * a byte. 30 | */ 31 | I2C::I2CStatus I2C::readReg(uint8_t addr, uint8_t reg, uint8_t* output) { 32 | I2C_RETURN_IF_ERR(write(addr, reg)); 33 | return read(addr, output); 34 | } 35 | 36 | I2C::I2CStatus I2C::writeReg(uint8_t addr, uint8_t* reg, uint8_t regLength, uint8_t* bytes, uint8_t length) { 37 | I2C_RETURN_IF_ERR(write(addr, reg, regLength)); 38 | return write(addr, bytes, length); 39 | } 40 | 41 | /** 42 | * Reading from a register with a non-8 byte address and a non-8 byte 43 | * response usually involves writing out the register address in groups 44 | * of 8 bytes starting with the MSB. Reading the response is also done, 45 | * starting with the LSB. 46 | */ 47 | I2C::I2CStatus I2C::readReg(uint8_t addr, uint8_t* reg, uint8_t regLength, uint8_t* bytes, uint8_t length) { 48 | // Write out register address 49 | I2C_RETURN_IF_ERR(write(addr, reg, regLength)); 50 | 51 | // Read in response 52 | I2C_RETURN_IF_ERR(read(addr, bytes, length)); 53 | 54 | return I2C::I2CStatus::OK; 55 | } 56 | 57 | } // namespace core::io 58 | -------------------------------------------------------------------------------- /samples/i2c/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example that handles I2C communication between an Arduino and a 3 | * EVT-Core device. 4 | * 5 | * The sample will read two bytes from the Arduino which should contain 6 | * the bytes "o" and "k". 7 | */ 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace io = core::io; 16 | namespace time = core::time; 17 | 18 | /** The address of the arduino listening for I2C requests */ 19 | constexpr uint8_t I2C_SLAVE_ADDR = 0x04; 20 | /** The "register" location of the "o" byte */ 21 | constexpr uint8_t O_REGISTER = 0x00; 22 | /** The "register" location of the "k" byte */ 23 | constexpr uint8_t K_REGISTER = 0x01; 24 | 25 | int main() { 26 | // Initialize system 27 | core::platform::init(); 28 | 29 | io::I2C& i2c = io::getI2C(); 30 | io::UART& uart = io::getUART(9600); 31 | 32 | uart.printf("Starting I2C test\n\r"); 33 | 34 | while (1) { 35 | uart.printf("Requesting first byte\n\r"); 36 | 37 | // Read the value of 'o' 38 | uint8_t oValue; 39 | io::I2C::I2CStatus status = i2c.readReg(I2C_SLAVE_ADDR, O_REGISTER, &oValue); 40 | if (status != io::I2C::I2CStatus::OK) { 41 | uart.printf("Failed read 'o' register with I2C::I2CStatus: %d\n\r", status); 42 | break; 43 | } 44 | 45 | uart.printf("Reading second bytes\n\r"); 46 | 47 | // Read the value of 'k' 48 | uint8_t kValue; 49 | status = i2c.readReg(I2C_SLAVE_ADDR, K_REGISTER, &kValue); 50 | if (status != io::I2C::I2CStatus::OK) { 51 | uart.printf("Failed read 'k' register with I2C::I2CStatus: %d\n\r", status); 52 | break; 53 | } 54 | 55 | uart.printf("Bytes Read: %c %c\n\r", oValue, kValue); 56 | 57 | // Wait half a second before repeating the test 58 | time::wait(500); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /cmake/evt-core_clang-format.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | CMake include file that creates a custom target to apply standardized formatting to all C++ files in 3 | the project. 4 | Requires: clang-format (v. 12 or higher) is downloaded 5 | ]]# 6 | 7 | include_guard(GLOBAL) 8 | 9 | # Get all project files for for the current project only 10 | file(GLOB_RECURSE 11 | ALL_CXX_SOURCE_FILES 12 | ${CMAKE_SOURCE_DIR}/src/*.[ch]pp ${CMAKE_SOURCE_DIR}/src/*.[CH] 13 | ${CMAKE_SOURCE_DIR}/include/*.[ch]pp ${CMAKE_SOURCE_DIR}/include/*.[CH] 14 | ${CMAKE_SOURCE_DIR}/targets/*.[ch]pp ${CMAKE_SOURCE_DIR}/targets/*.[CH] 15 | ${CMAKE_SOURCE_DIR}/samples/*.[ch]pp ${CMAKE_SOURCE_DIR}/samples/*.[CH] 16 | ) 17 | 18 | # Get the path to clang-format 19 | find_program(CLANG_FORMAT "clang-format") 20 | # Create the formatting target if clang-format is found 21 | if(CLANG_FORMAT) 22 | message(STATUS "Found clang-format: ${CLANG_FORMAT}") 23 | 24 | add_custom_target(clang-format) 25 | # Loop through each file and create a separate command because Windows has a 128-character limit 26 | # on its commands 27 | foreach(src_file ${ALL_CXX_SOURCE_FILES}) 28 | add_custom_command(TARGET clang-format PRE_BUILD 29 | COMMAND ${CLANG_FORMAT} -i -style=file ${src_file} 30 | ) 31 | endforeach() 32 | else() 33 | message(WARNING "clang-format not found") 34 | endif() 35 | 36 | 37 | #################################################################################################### 38 | # How to set up clang-format 39 | #################################################################################################### 40 | 41 | #[[ 42 | Linux: 43 | $ sudo apt-get install clang-format 44 | $ sudo apt-get install clang-format-12 45 | $ sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-12 100 46 | 47 | Windows: 48 | 1. Download the installer from https://llvm.org/builds/. 49 | 2. Run the installer, making sure you choose the option to add to the PATH variable. 50 | ]]# -------------------------------------------------------------------------------- /samples/adc/multi_adc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This example shows off the use of the ADC. Two pins are setup for ADC 3 | * functionality and the values are continuously read in and printed over 4 | * UART. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace io = core::io; 13 | namespace time = core::time; 14 | 15 | int main() { 16 | // Initialize system 17 | core::platform::init(); 18 | 19 | io::UART& uart = io::getUART(9600); 20 | 21 | // Set up the logger to catch errors in ADC creation 22 | core::log::LOGGER.setUART(&uart); 23 | core::log::LOGGER.setLogLevel(core::log::Logger::LogLevel::INFO); 24 | 25 | uart.printf("Starting ADC test\r\n"); 26 | 27 | time::wait(500); 28 | 29 | io::ADC& adc0 = io::getADC(); 30 | io::ADC& adc1 = io::getADC(); 31 | 32 | while (1) { 33 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------"); 34 | core::log::LOGGER.log( 35 | core::log::Logger::LogLevel::INFO, "ADC0 : %d mV", static_cast(adc0.read() * 1000)); 36 | core::log::LOGGER.log( 37 | core::log::Logger::LogLevel::INFO, "ADC0: %d%%", static_cast(adc0.readPercentage() * 100)); 38 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "ADC0 raw: %d", adc0.readRaw()); 39 | core::log::LOGGER.log( 40 | core::log::Logger::LogLevel::INFO, "ADC1 : %d mV", static_cast(adc1.read() * 1000)); 41 | core::log::LOGGER.log( 42 | core::log::Logger::LogLevel::INFO, "ADC1: %d%%", static_cast(adc1.readPercentage() * 100)); 43 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "ADC1 raw: %d", adc1.readRaw()); 44 | core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------\r\n"); 45 | time::wait(500); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /include/core/dev/RTCTimer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVT_TIMER_H 2 | #define EVT_TIMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace time = core::time; 9 | 10 | namespace core::dev { 11 | 12 | class RTCTimer : public Timer { 13 | public: 14 | /** 15 | * Create instance of RTCTimer. 16 | * clock period defaults to 1s. 17 | * 18 | * @param r 19 | */ 20 | RTCTimer(RTC& r); 21 | 22 | /** 23 | * Create instance of RTCTimer. 24 | * 25 | * @param[in] r Instance of on-board 26 | * @param[in] clock Amount of time it takes for the time to go off in ms 27 | */ 28 | RTCTimer(RTC& r, uint32_t clock); 29 | 30 | /** 31 | * not implemented. 32 | * 33 | * @param[in] irqHandler The IRQ Handler function pointer. Sets a new interrupt handler function 34 | */ 35 | void startTimer(void (*irqHandler)(void* htim)) override {} 36 | 37 | void startTimer() override; 38 | 39 | void stopTimer() override; 40 | 41 | void reloadTimer() override; 42 | 43 | void setPeriod(uint32_t clock) override; 44 | 45 | /** 46 | * Gets the time since the RTC clock began in seconds 47 | * 48 | * @return the time since the RTC clock began 49 | */ 50 | uint32_t getTime(); 51 | 52 | /** 53 | * Gets whether the timer has gone off 54 | * 55 | * @return whether the time has gone off 56 | */ 57 | bool hasGoneOff(); 58 | 59 | private: 60 | /** Instance of on-board*/ 61 | RTC& rtc; 62 | 63 | /** 64 | * The amount of seconds that have elapsed while the timer is running. 65 | * Only updates when stopTimer() is called. 66 | */ 67 | uint32_t time; 68 | 69 | /** The amount of time it takes the timer to go off in SECONDS */ 70 | uint32_t clockPeriod; 71 | 72 | /** The epoc time the clock started */ 73 | uint32_t startTime; 74 | 75 | /** true if timer has been stopped */ 76 | bool bTimerStopped; 77 | }; 78 | 79 | } // namespace core::dev 80 | 81 | #endif // EVT_TIMER_H 82 | -------------------------------------------------------------------------------- /src/core/platform/f3xx/stm32f302x8.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace core::platform { 8 | 9 | void stm32f3xx_init() { 10 | HAL_Init(); 11 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 12 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 13 | RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; 14 | 15 | /** 16 | * Initializes the RCC Oscillators according to the specified parameters 17 | * in the RCC_OscInitTypeDef structure. 18 | */ 19 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; 20 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; 21 | RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 22 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 23 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 24 | RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8; // PLL CLK at 8 / 2 * 8 = 32 MHz 25 | HAL_RCC_OscConfig(&RCC_OscInitStruct); 26 | 27 | /** 28 | * Initializes the CPU, AHB and APB buses clocks 29 | */ 30 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; 31 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // SYSCLK at 32 MHz (PLL CLK) 32 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 33 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 34 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 35 | 36 | HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); 37 | 38 | // ADC is currently configured to run based on AHB clock. 39 | // Enable the PLL Clock below and update 'halADC.Init.ClockPrescaler' to run ADC using faster PLL clock 40 | /* 41 | PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC1; 42 | PeriphClkInit.Adc1ClockSelection = RCC_ADC1PLLCLK_DIV1; 43 | 44 | HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); 45 | */ 46 | 47 | SysTick_Handler(); 48 | } 49 | 50 | } // namespace core::platform 51 | -------------------------------------------------------------------------------- /include/core/dev/platform/f3xx/Timerf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_TIMER3xx_H 2 | #define _EVT_TIMER3xx_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace core::dev { 11 | 12 | /** 13 | * Implementation of the Timer class for STM32f3xx MCUs 14 | */ 15 | class Timerf3xx : public Timer { 16 | public: 17 | /** 18 | * Will initialize the timer device on the STM with the given period and the given IRQ Handler 19 | * that triggers with the given period. Starts the timer 20 | * @param timerPeripheral[in] The timer peripheral to configure. Possible options for this board are 21 | * TIM2, TIM15, TIM16, TIM17. It is up to the user to verify that resource conflicts 22 | * do not occur. 23 | * 24 | * @param[in] timerPeripheral The timer to use 25 | * @param[in] clockPeriod the clock period in ms. An interrupt will be triggered at that frequency. 26 | */ 27 | explicit Timerf3xx(TIM_TypeDef* timerPeripheral, uint32_t clockPeriod); 28 | 29 | void startTimer(void (*irqHandler)(void* htim)) override; 30 | 31 | void startTimer() override; 32 | 33 | void stopTimer() override; 34 | 35 | void reloadTimer() override; 36 | 37 | void setPeriod(uint32_t clockPeriod) override; 38 | 39 | private: 40 | // Pointer to the halTimer struct stored in the global array in Timerf3xx.cpp 41 | TIM_HandleTypeDef* halTimer; 42 | 43 | // Timer clock period 44 | uint32_t clockPeriod; 45 | 46 | /** 47 | * Handles the initialization of the timer module. Actually configures the device and enables it. 48 | * @param[in] timerPeripheral The timer peripheral to configure. Possible options for this board are 49 | * TIM2, TIM15, TIM16, TIM17. It is up to the user to verify that resource conflicts do not occur. 50 | * @param[in] clockPeriod the clock period in ms. An interrupt will be triggered at that frequency. 51 | */ 52 | void initTimer(TIM_TypeDef* timerPeripheral, uint32_t clockPeriod); 53 | }; 54 | 55 | } // namespace core::dev 56 | 57 | #endif //_EVT_TIMER3xx_H 58 | -------------------------------------------------------------------------------- /samples/lcd/lcd-ball/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample code for displaying a moving ball animation on an LCD. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace dev = core::dev; 12 | namespace io = core::io; 13 | namespace time = core::time; 14 | 15 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; 16 | 17 | constexpr uint8_t deviceCount = 1; 18 | 19 | io::GPIO* devices[deviceCount]; 20 | 21 | int main() { 22 | // Initialize system 23 | core::platform::init(); 24 | 25 | // Setup UART 26 | io::UART& uart = io::getUART(9600); 27 | 28 | // Uses HUDL 1.0 Pins 29 | io::GPIO& regSelect = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 30 | io::GPIO& reset = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 31 | 32 | devices[0] = &io::getGPIO(core::io::GPIO::Direction::OUTPUT); 33 | devices[0]->writePin(io::GPIO::State::HIGH); 34 | 35 | // Setup SPI 36 | io::SPI& spi = io::getSPI(devices, deviceCount); 37 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE0, SPI_MSB_FIRST); 38 | 39 | // Sets up LCD 40 | uart.printf("Creating LCD Object...\n\r"); 41 | core::dev::LCD lcd(regSelect, reset, spi); 42 | uart.printf("Initializing LCD...\n\r"); 43 | lcd.initLCD(); 44 | lcd.clearLCD(); 45 | 46 | uint8_t ball[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 47 | uint8_t col = 0; 48 | uint8_t page = 0; 49 | 50 | lcd.displayBitMapInArea(ball, 8, 1, page, col); 51 | 52 | while (true) { 53 | lcd.clearArea(8, 1, page, col); 54 | 55 | col++; 56 | if (col >= 128) { 57 | col = 0; 58 | page++; 59 | 60 | if (page > 7) { 61 | page = 0; 62 | } 63 | } 64 | 65 | lcd.displayBitMapInArea(ball, 8, 1, page, col); 66 | 67 | time::wait(300); 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /include/core/io/platform/f3xx/I2Cf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_I2Cf3xx_ 2 | #define _EVT_I2Cf3xx_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #ifndef EVT_I2C_TIMEOUT 11 | #define EVT_I2C_TIMEOUT 100 12 | #endif 13 | 14 | namespace core::io { 15 | 16 | class I2Cf3xx : public I2C { 17 | public: 18 | /** 19 | * Make an instance of an I2C interface for the F3. Will determine 20 | * which I2C bus of the STM to use based on the provided pins. 21 | * 22 | * @param[in] sclPin The I2C clock pin 23 | * @param[in] sdaPin The I2C data pin 24 | */ 25 | I2Cf3xx(Pin sclPin, Pin sdaPin); 26 | 27 | I2C::I2CStatus write(uint8_t addr, uint8_t byte) override; 28 | 29 | I2C::I2CStatus read(uint8_t addr, uint8_t* output) override; 30 | 31 | I2C::I2CStatus write(uint8_t addr, uint8_t* bytes, uint8_t length) override; 32 | 33 | I2C::I2CStatus read(uint8_t addr, uint8_t* bytes, uint8_t length) override; 34 | 35 | I2C::I2CStatus writeMemReg(uint8_t addr, uint32_t memAddress, uint8_t byte, uint16_t memAddSize, 36 | uint8_t maxWriteTime) override; 37 | 38 | I2C::I2CStatus readMemReg(uint8_t addr, uint32_t memAddress, uint8_t* byte, uint16_t memAddSize) override; 39 | 40 | I2C::I2CStatus writeMemReg(uint8_t addr, uint32_t memAddress, uint8_t* bytes, uint8_t size, uint16_t memAddSize, 41 | uint8_t maxWriteTime) override; 42 | 43 | I2C::I2CStatus readMemReg(uint8_t addr, uint32_t memAddress, uint8_t* bytes, uint8_t size, 44 | uint16_t memAddSize) override; 45 | 46 | private: 47 | constexpr static uint32_t DEFAULT_I2C_FREQ = 100000; 48 | 49 | /** Interface into the HAL */ 50 | I2C_HandleTypeDef halI2C = {}; 51 | 52 | /** 53 | * Convert the STM HAL status to an I2C::I2CStatus 54 | * 55 | * @param[in] halStatus The HAL status 56 | * @return The I2C::I2CStatus 57 | */ 58 | static I2C::I2CStatus halToI2CStatus(HAL_StatusTypeDef halStatus); 59 | }; 60 | 61 | } // namespace core::io 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/core/io/platform/f4xx/I2Cf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_I2Cf4xx_ 2 | #define _EVT_I2Cf4xx_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #ifndef EVT_I2C_TIMEOUT 11 | #define EVT_I2C_TIMEOUT 100 12 | #endif 13 | 14 | namespace core::io { 15 | 16 | class I2Cf4xx : public I2C { 17 | public: 18 | /** 19 | * Make an instance of an I2C interface for the F4. Will determine 20 | * which I2C bus of the STM to use based on the provided pins. 21 | * 22 | * @param[in] sclPin The I2C clock pin 23 | * @param[in] sdaPin The I2C data pin 24 | */ 25 | I2Cf4xx(Pin sclPin, Pin sdaPin); 26 | 27 | I2C::I2CStatus write(uint8_t addr, uint8_t byte) override; 28 | 29 | I2C::I2CStatus read(uint8_t addr, uint8_t* output) override; 30 | 31 | I2C::I2CStatus write(uint8_t addr, uint8_t* bytes, uint8_t length) override; 32 | 33 | I2C::I2CStatus read(uint8_t addr, uint8_t* bytes, uint8_t length) override; 34 | 35 | I2C::I2CStatus writeMemReg(uint8_t addr, uint32_t memAddress, uint8_t byte, uint16_t memAddSize, 36 | uint8_t maxWriteTime) override; 37 | 38 | I2C::I2CStatus readMemReg(uint8_t addr, uint32_t memAddress, uint8_t* byte, uint16_t memAddSize) override; 39 | 40 | I2C::I2CStatus writeMemReg(uint8_t addr, uint32_t memAddress, uint8_t* bytes, uint8_t size, uint16_t memAddSize, 41 | uint8_t maxWriteTime) override; 42 | 43 | I2C::I2CStatus readMemReg(uint8_t addr, uint32_t memAddress, uint8_t* bytes, uint8_t size, 44 | uint16_t memAddSize) override; 45 | 46 | private: 47 | constexpr static uint32_t DEFAULT_I2C_FREQ = 100000; 48 | 49 | /** Interface into the HAL */ 50 | I2C_HandleTypeDef halI2C = {}; 51 | 52 | /** 53 | * Convert the STM HAL status to an I2C::I2CStatus 54 | * 55 | * @param[in] halStatus The HAL status 56 | * @return The I2C::I2CStatus 57 | */ 58 | static I2C::I2CStatus halToI2CStatus(HAL_StatusTypeDef halStatus); 59 | }; 60 | 61 | } // namespace core::io 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/core/utils/log.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_EVT_UTILS_LOG_HPP_ 2 | #define INCLUDE_EVT_UTILS_LOG_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace dev = core::dev; 9 | 10 | namespace core::log { 11 | /** To enable the logger, compile with "cmake -D EVT_CORE_LOG_ENABLE" */ 12 | class Logger { 13 | public: 14 | /** 15 | * The level at which messages should be logged 16 | */ 17 | enum class LogLevel { 18 | DEBUG = 0u, 19 | INFO = 1u, 20 | WARNING = 2u, 21 | ERROR = 3u, 22 | }; 23 | 24 | /** 25 | * Set the UART to be used for logging 26 | * 27 | * @param[in] uart UART to be used for logging 28 | */ 29 | void setUART(io::UART* uart); 30 | 31 | /** 32 | * Set the minimum log level to be displayed by the logger 33 | * 34 | * @param[in] level Minimum log level to be displayed by the logger 35 | */ 36 | void setLogLevel(LogLevel level); 37 | 38 | /** 39 | * Set the clock to be used for timestamps 40 | * 41 | * @param[in] rtc Clock to be used for timestamps 42 | */ 43 | void setClock(dev::RTC* rtc); 44 | 45 | /** 46 | * Write the formatted string to the serial logger if the logger log level 47 | * reaches this level 48 | * 49 | * @param[in] level Log level of this statement 50 | * @param[in] format Format string to be logged 51 | * @param[in] ... Variables to be formatted into the log statement 52 | */ 53 | void log(LogLevel level, const char* format, ...); 54 | 55 | private: 56 | /** UART to be used for logging */ 57 | io::UART* uart; 58 | /** Minimum log level to be displayed by the logger */ 59 | LogLevel minLevel; 60 | /** Clock to be used for timestamps */ 61 | dev::RTC* clock; 62 | }; 63 | 64 | // extern keyword ensures exactly 1 instance of LOGGER is created instead of 65 | // creating a new one each time this header is included 66 | /** Global Logger instance */ 67 | extern Logger LOGGER; 68 | 69 | } // namespace core::log 70 | 71 | #endif // INCLUDE_EVT_UTILS_LOG_HPP_ 72 | -------------------------------------------------------------------------------- /include/core/rtos/Initializable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_RTOS_INITIALIZABLE_ 2 | #define _EVT_RTOS_INITIALIZABLE_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifndef INITIALIZABLE_NAME_MAX_LENGTH 9 | #define INITIALIZABLE_NAME_MAX_LENGTH 26 10 | #endif // INITIALIZABLE_NAME_MAX_LENGTH 11 | 12 | namespace core::rtos { 13 | 14 | /** 15 | * Abstract class that represents a ThreadX wrapper object that must be passed into the 16 | * Threadx::startKernel() method as part of the initList parameter. 17 | */ 18 | class Initializable { 19 | public: 20 | /** 21 | * Initialize this object with the kernel 22 | * 23 | * @param pool The byte pool that this initializable object will be stored in 24 | * @return The first error found by the function or TXE_SUCCESS if there was no error 25 | */ 26 | virtual TXError init(BytePoolBase& pool) = 0; 27 | 28 | /** 29 | * Copy the name of this Initializable object into the character array pointed to by destination & 30 | * insert a null-terminating character at the end of the given array for safety 31 | * 32 | * @param[out] destination Character array to copy the name into. 33 | * Should be INITIALIZABLE_NAME_MAX_LENGTH bytes long 34 | * @param[in] size the size of the output array. Should be INITIALIZABLE_NAME_MAX_LENGTH bytes, unless you 35 | * want the name to be truncated. If the given size is larger than INITIALIZABLE_NAME_MAX_LENGTH, it will be 36 | * set to INITIALIZABLE_NAME_MAX_LENGTH 37 | */ 38 | void getName(char* destination, size_t size); 39 | 40 | protected: 41 | /** 42 | * Initializable constructor 43 | * @param[in] name pointer to the name of the Initializable. The first INITIALIZABLE_NAME_MAX_LENGTH bytes of the 44 | * name will be copied into the local name array. 45 | */ 46 | explicit Initializable(char* name); 47 | 48 | /** 49 | * The name of this initializable object 50 | */ 51 | char name[INITIALIZABLE_NAME_MAX_LENGTH]; 52 | }; 53 | 54 | } // namespace core::rtos 55 | 56 | #endif //_EVT_RTOS_INITIALIZABLE_ 57 | -------------------------------------------------------------------------------- /samples/spi/ADXL345/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example that handles SPI communication between an EVT-Core 3 | * device and the ADXL345 accelerometer 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace io = core::io; 14 | namespace time = core::time; 15 | 16 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; // 500KHz 17 | 18 | constexpr uint8_t deviceCount = 1; 19 | 20 | #define ADXL345_REG_POWER_CTL 0x2D // R/W 00000000 Power-saving features control ---- 21 | #define ADXL345_REG_DATAY0 0x34 // R 00000000 Y-Axis Data 0 22 | 23 | io::GPIO* devices[deviceCount]; 24 | 25 | int main() { 26 | // Initialize system 27 | core::platform::init(); 28 | 29 | devices[0] = &io::getGPIO(io::GPIO::Direction::OUTPUT); 30 | devices[0]->writePin(io::GPIO::State::HIGH); 31 | 32 | io::SPI& spi = io::getSPI(devices, deviceCount); 33 | 34 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE3, SPI_MSB_FIRST); 35 | 36 | io::UART& uart = io::getUART(9600); 37 | 38 | uart.printf("Starting SPI test\n\r"); 39 | uint8_t byte = 0; 40 | while (byte != 0xE5) { 41 | io::SPI::SPIStatus status = spi.readReg(0, 0x00 | 0x80, &byte); 42 | if (status != io::SPI::SPIStatus::OK) { 43 | uart.printf("SPI readReg Error!\n\r"); 44 | } 45 | 46 | uart.printf("device ID: 0x%X, %d\n\r", byte, byte == 0xE5); // should be 0xE5 47 | time::wait(500); 48 | } 49 | spi.writeReg(0, ADXL345_REG_POWER_CTL, 0x08); 50 | 51 | int16_t data; 52 | uint8_t bytes[2]; 53 | while (1) { 54 | spi.startTransmission(0); 55 | spi.write(ADXL345_REG_DATAY0 | 0x80 | 0x40); 56 | spi.read(bytes, 2); 57 | data = bytes[0] | bytes[1] << 8; 58 | spi.endTransmission(0); 59 | uart.printf("Y: %i\n\r", data); 60 | 61 | // Wait half a second before repeating the test 62 | time::wait(500); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /include/core/utils/bits.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides a series of utilities for operating on the binary representation 3 | * of a number. These utilites are commonly used operations that may be needed. 4 | */ 5 | 6 | #ifndef _BITS_H_ 7 | #define _BITS_H_ 8 | 9 | #include 10 | 11 | // 16 bit operations 12 | /** 13 | * Get the high byte from the number. 14 | * 15 | * @param data The number to get the high byte from 16 | * @return The high order byte 17 | */ 18 | constexpr static inline uint8_t getHighByte(uint16_t data) { 19 | return static_cast((data & 0xFF00) >> 8); 20 | } 21 | 22 | /** 23 | * Get the low byte from the number. 24 | * 25 | * @param data The number to get the low byte from 26 | * @return The low order byte 27 | */ 28 | constexpr static inline uint8_t getLowByte(uint16_t data) { 29 | return static_cast(data & 0x00FF); 30 | } 31 | 32 | // 32 bit operations 33 | /** 34 | * Get the highest byte from the number 35 | * 36 | * @param data The number to get the highest byte from 37 | * @return The highest order byte 38 | */ 39 | constexpr static inline uint8_t getHighestByte(uint32_t data) { 40 | return static_cast((data & 0xFF000000) >> 24); 41 | } 42 | 43 | /** 44 | * Get the upper middle byte from the number. 45 | * 46 | * @param data The number to get the upper middle byte from 47 | * @return The upper middle order byte 48 | */ 49 | constexpr static inline uint8_t getMiddleHighByte(uint32_t data) { 50 | return static_cast((data & 0x00FF0000) >> 16); 51 | } 52 | 53 | /** 54 | * Get the lower middle byte from the number. 55 | * 56 | * @param data The number to get the lower middle byte from. 57 | * @return The lower middle order byte 58 | */ 59 | constexpr static inline uint8_t getMiddleLowByte(uint32_t data) { 60 | return static_cast((data & 0x0000FF00) >> 8); 61 | } 62 | 63 | /** 64 | * The the lowest byte from the number. 65 | * 66 | * @param data The number to get the lowest byte from. 67 | * @return The lowest order byte 68 | */ 69 | constexpr static inline uint8_t getLowestByte(uint32_t data) { 70 | return static_cast((data & 0x000000FF)); 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /include/core/dev/storage/M24C32.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVT_M24C32 2 | #define EVT_M24C32 3 | 4 | #include 5 | #include 6 | 7 | namespace core::dev { 8 | 9 | class M24C32 : public EEPROM { 10 | public: 11 | /** 12 | * Start up the EEPROM with a slave address of i2cSlaveAddress and 13 | * I2C instance i2c 14 | * 15 | * @param[in] i2cSlaveAddress Slave address to use for I2C communication 16 | * @param[in] i2c I2C instance to communicate over 17 | */ 18 | M24C32(uint8_t i2cSlaveAddress, io::I2C& i2c); 19 | 20 | uint8_t readByte(uint32_t address) override; 21 | 22 | uint16_t readHalfWord(uint32_t address) override; 23 | 24 | uint32_t readWord(uint32_t address) override; 25 | 26 | void readBytes(uint32_t address, uint8_t* buffer, uint8_t numBytes) override; 27 | 28 | void readHalfWords(uint8_t address, uint16_t* buffer, uint8_t numHWords) override; 29 | 30 | void readWords(uint8_t address, uint32_t* buffer, uint8_t numWords) override; 31 | 32 | void writeByte(uint32_t address, uint8_t data) override; 33 | 34 | void writeHalfWord(uint32_t address, uint16_t data) override; 35 | 36 | void writeWord(uint32_t address, uint32_t data) override; 37 | 38 | void writeBytes(uint32_t address, uint8_t* dataArr, uint8_t numBytes) override; 39 | 40 | void writeHalfWords(uint8_t address, uint16_t* dataArr, uint8_t numHWords) override; 41 | 42 | void writeWords(uint8_t address, uint32_t* dataArr, uint8_t numWords) override; 43 | 44 | private: 45 | /** 46 | * Size of the memory address of this EEPROM 47 | * The value is 2 because it has 2-byte addresses 48 | */ 49 | static constexpr uint8_t MEM_ADDRESS_SIZE = 2; 50 | /** Maximum time to write a single byte of this EEPROM */ 51 | static constexpr uint8_t MAX_WRITE_TIME = 5; 52 | /** Number of bytes that make up a page size */ 53 | static constexpr uint8_t PAGE_SIZE = 32; 54 | /** Slave address for this device to be used for I2C communication */ 55 | uint8_t i2cSlaveAddress; 56 | /** I2C instance to be used for I2C communication */ 57 | io::I2C& i2c; 58 | }; 59 | 60 | } // namespace core::dev 61 | 62 | #endif // EVT_M24C32 63 | -------------------------------------------------------------------------------- /libs/HALf4/include/HALf4/stm32_assert_template.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32_assert.h 4 | * @author MCD Application Team 5 | * @brief STM32 assert template file. 6 | * This file should be copied to the application folder and renamed 7 | * to stm32_assert.h. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * Copyright (c) 2017 STMicroelectronics. 12 | * All rights reserved. 13 | * 14 | * This software is licensed under terms that can be found in the LICENSE file 15 | * in the root directory of this software component. 16 | * If no LICENSE file comes with this software, it is provided AS-IS. 17 | * 18 | ****************************************************************************** 19 | */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __STM32_ASSERT_H 23 | #define __STM32_ASSERT_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Exported types ------------------------------------------------------------*/ 30 | /* Exported constants --------------------------------------------------------*/ 31 | /* Includes ------------------------------------------------------------------*/ 32 | /* Exported macro ------------------------------------------------------------*/ 33 | #ifdef USE_FULL_ASSERT 34 | /** 35 | * @brief The assert_param macro is used for function's parameters check. 36 | * @param expr If expr is false, it calls assert_failed function 37 | * which reports the name of the source file and the source 38 | * line number of the call that failed. 39 | * If expr is true, it returns no value. 40 | * @retval None 41 | */ 42 | #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) 43 | /* Exported functions ------------------------------------------------------- */ 44 | void assert_failed(uint8_t* file, uint32_t line); 45 | #else 46 | #define assert_param(expr) ((void)0U) 47 | #endif /* USE_FULL_ASSERT */ 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* __STM32_ASSERT_H */ 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. EVT-core documentation master file, created by 2 | sphinx-quickstart on Sat Sep 4 10:17:15 2021. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ======== 7 | EVT-core 8 | ======== 9 | 10 | Introduction 11 | ============ 12 | 13 | What is EVT 14 | ----------- 15 | 16 | EVT stands for Electric Vehicle Team at RIT. We build and race electric 17 | vehicles. Currently we have two track motorcycles and we are developing for 18 | an electric dirt bike. 19 | 20 | Firmware in EVT 21 | --------------- 22 | 23 | In EVT the Firmware team has the responsibility for desigining, developing, 24 | and maintaining the software that is associated with the team. The bulk of 25 | the software is in the form of the firmware that runs on our custom hardware. 26 | 27 | As an interdisiplinary team, the Firmware teams directly interfaces with the 28 | other sub-teams at EVT. Most noteably we work directly with the Electrical 29 | team in the design and testing of firmware. 30 | 31 | What is EVT-core 32 | ---------------- 33 | 34 | EVT-core is the main library that the rest of the firmware is based around. 35 | The library is designed to be an abstraction layer between the application 36 | level firmware and the microcontroller. EVT-core is not a full RTOS, but 37 | instead aims to abstract common IO interfaces and devices that the team 38 | interacts with. As such we include interfaces for I2C, PWM, UART, CAN, etc. 39 | 40 | How do I Get Started with EVT-core? 41 | ----------------------------------- 42 | 43 | To get started visit the `EVT-core repository `_. 44 | The README will go over the high level process for building the code. The 45 | project is built using CMake and requires an environment variable containing 46 | the location of the GCC ARM toolchain. The README will go over setting the 47 | environment variable and building EVT-core. 48 | 49 | Several samples are included in EVT-core directly. As a libary, EVT-core can 50 | be linked against in external projects. 51 | 52 | .. toctree:: 53 | :maxdepth: 2 54 | :caption: Contents: 55 | 56 | design/index.rst 57 | api/index.rst 58 | canopen.rst 59 | glossary.rst 60 | -------------------------------------------------------------------------------- /src/core/rtos/Semaphore.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::rtos { 4 | 5 | Semaphore::Semaphore(char* name, uint32_t initialCount) 6 | : Initializable(name), txSemaphore(), initialCount(initialCount) {} 7 | 8 | TXError Semaphore::init(BytePoolBase& pool) { 9 | return static_cast(tx_semaphore_create(&txSemaphore, name, initialCount)); 10 | } 11 | 12 | Semaphore::~Semaphore() { 13 | tx_semaphore_delete(&txSemaphore); 14 | } 15 | 16 | TXError Semaphore::get(uint32_t waitOption) { 17 | return static_cast(tx_semaphore_get(&txSemaphore, waitOption)); 18 | } 19 | 20 | TXError Semaphore::put() { 21 | return static_cast(tx_semaphore_put(&txSemaphore)); 22 | } 23 | 24 | TXError Semaphore::registerNotifyFunction(void (*notifyFunction)(Semaphore*)) { 25 | // TODO: registerNotifyFunction must be implemented 26 | return TXE_FEATURE_NOT_ENABLED; 27 | } 28 | 29 | TXError Semaphore::prioritize() { 30 | return static_cast(tx_semaphore_prioritize(&txSemaphore)); 31 | } 32 | 33 | TXError Semaphore::putWithCeiling(uint32_t ceiling) { 34 | return static_cast(tx_semaphore_ceiling_put(&txSemaphore, ceiling)); 35 | } 36 | 37 | TXError Semaphore::getCount(uint32_t* currentCount) { 38 | uint32_t status = tx_semaphore_info_get(&txSemaphore, nullptr, currentCount, nullptr, nullptr, nullptr); 39 | return static_cast(status); 40 | } 41 | 42 | TXError Semaphore::getNameOfFirstSuspendedThread(char** threadName) { 43 | TX_THREAD* thread; 44 | uint32_t status = tx_semaphore_info_get(&txSemaphore, nullptr, nullptr, &thread, nullptr, nullptr); 45 | // exit early if the call failed 46 | if (status != TXE_SUCCESS) { 47 | return static_cast(status); 48 | } 49 | 50 | // read the name off the struct 51 | status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); 52 | return static_cast(status); 53 | } 54 | 55 | TXError Semaphore::getNumSuspendedThreads(uint32_t* numSuspendedThreads) { 56 | uint32_t status = tx_semaphore_info_get(&txSemaphore, nullptr, nullptr, nullptr, numSuspendedThreads, nullptr); 57 | return static_cast(status); 58 | } 59 | 60 | } // namespace core::rtos 61 | -------------------------------------------------------------------------------- /.vscode/tasks.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "cmake", 6 | "label": "CMake: clean", 7 | "command": "clean", 8 | "preset": "__defaultBuildPreset__", 9 | "problemMatcher": [], 10 | "detail": "CMake clean task" 11 | }, 12 | { 13 | "type": "cmake", 14 | "label": "CMake: build", 15 | "command": "build", 16 | "targets": [ 17 | "all" 18 | ], 19 | "preset": "__defaultBuildPreset__", 20 | "group": "build", 21 | "problemMatcher": [], 22 | "detail": "CMake build task" 23 | }, 24 | { 25 | "type": "cmake", 26 | "label": "CMake: clean rebuild", 27 | "command": "cleanRebuild", 28 | "targets": [ 29 | "all" 30 | ], 31 | "preset": "__defaultBuildPreset__", 32 | "group": "build", 33 | "problemMatcher": [], 34 | "detail": "CMake clean rebuild task" 35 | }, 36 | { 37 | "type": "shell", 38 | "label": "flash debug", 39 | "command": "${command:workbench.action.debug.start}", 40 | "detail": "Flash code and launch the debugger" 41 | }, 42 | { 43 | "type": "shell", 44 | "label": "Flash project", 45 | "command": "${env:STM32_PRG_PATH}\\STM32_Programmer_CLI", 46 | "windows":{ 47 | "command": "${env:STM32_PRG_PATH}\\STM32_Programmer_CLI.exe" 48 | }, 49 | "args": [ 50 | "--connect", 51 | "port=swd", 52 | "mode=UR", //Under reset 53 | "--download", "${input:fileDirnameForwardSlash}", 54 | "-hardRst", // Hardware reset - if rst pin is connected 55 | "-rst", // Software reset (backup) 56 | "--start" // Start execution 57 | ], 58 | "options": { 59 | "cwd": "${workspaceFolder}" 60 | }, 61 | "problemMatcher": [] 62 | } 63 | ], 64 | "inputs": [ 65 | { 66 | "id": "fileDirnameForwardSlash", 67 | "type": "command", 68 | "command": "extension.commandvariable.transform", 69 | "args": { 70 | "text": "${command:cmake.launchTargetPath}", 71 | "find": "\\\\", // Reason for four '\': https://stackoverflow.com/a/4025505/2909854 72 | "replace": "/", 73 | "flags": "g" 74 | } 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /include/core/rtos/Threadx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EVT_RTOS_THREADX_ 2 | #define EVT_RTOS_THREADX_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * Converts seconds to rtos ticks 9 | */ 10 | #define S_TO_TICKS(n) ((uint32_t) (n) *TX_TIMER_TICKS_PER_SECOND) 11 | 12 | /** 13 | * Converts milliseconds to rtos ticks 14 | */ 15 | #define MS_TO_TICKS(n) ((uint32_t) (n) *TX_TIMER_TICKS_PER_SECOND / 1000u) 16 | 17 | namespace core::rtos { 18 | 19 | /** 20 | * Allocate a bytepool to store all of the Initializable objects passed into this function, initialize them, and begin 21 | * the threadx kernel 22 | * 23 | * @param[in] initList The list of Initializable objects that must be initialized before the threadx kernel begins 24 | * @param length The length of initList 25 | * @param[in] poolptr A reference to the bytepool to store the information of the initializable objects in 26 | * @return The first error found by the function or TXE_SUCCESS if there was no error 27 | */ 28 | TXError startKernel(Initializable** initList, std::size_t length, BytePoolBase& pool); 29 | 30 | /** 31 | * Initialize all members of initList into the current BytePool 32 | * 33 | * @param[in] initList The list of Initializable objects that must be initialized 34 | * before the threadx kernel begins 35 | * @param length The length of initList 36 | * @param[in] poolptr A reference to the bytepool to store the information of the initializable objects in 37 | * @return The first error found by the function or TXE_SUCCESS if there was no error 38 | */ 39 | TXError bulkInitialize(Initializable** initList, std::size_t length, BytePoolBase& pool); 40 | 41 | /** 42 | * Relinquish control of the cpu from the currently running thread, allowing the 43 | * threadx kernel to potentially pick another thread to run. 44 | * If the currently running thread is the highest priority thread running, this method will not have any effect 45 | */ 46 | void relinquish(); 47 | 48 | /** 49 | * Sleep the currently running thread for the given amount of time. If no thread is running returns an error 50 | * 51 | * @param sleepTime How long (in ticks) the thread should sleep for 52 | * @return The first error found by the function or TXE_SUCCESS if there was no error 53 | */ 54 | TXError sleep(uint32_t sleepTime); 55 | 56 | } // namespace core::rtos 57 | 58 | #endif // EVT_RTOS_THREADX_ 59 | -------------------------------------------------------------------------------- /samples/can/back_and_forth/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example of CAN communication between two devices. The two devices need 3 | * to be on a CAN network. The other device can be running this sample code 4 | * as well. 5 | * 6 | * @author Collin Bolles 7 | */ 8 | #include 9 | #include 10 | #include 11 | 12 | namespace io = core::io; 13 | namespace time = core::time; 14 | 15 | void canIRQHandler(io::CANMessage& message, void* priv) { 16 | io::UART* uart = (io::UART*) priv; 17 | uart->printf("Message received\r\n"); 18 | uart->printf("Message id: 0x%X \r\n", message.getId()); 19 | uart->printf("Message length: %d\r\n", message.getDataLength()); 20 | uart->printf("Message contents: "); 21 | 22 | uint8_t* message_payload = message.getPayload(); 23 | for (int i = 0; i < message.getDataLength(); i++) { 24 | uart->printf("0x%02X ", message_payload[i]); 25 | } 26 | uart->printf("\r\n\r\n"); 27 | } 28 | 29 | int main() { 30 | // Initialize system 31 | core::platform::init(); 32 | 33 | // Get CAN instance with loopback enabled 34 | io::CAN& can = io::getCAN(); 35 | io::UART& uart = io::getUART(9600); 36 | can.addIRQHandler(canIRQHandler, &uart); 37 | 38 | // CAN message that will be sent 39 | uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xBE, 0xEF, 0x00, 0x01, 0x02}; 40 | io::CANMessage transmit_message(1, 8, &payload[0], true); 41 | io::CANMessage received_message; 42 | 43 | uart.printf("Starting CAN testing\r\n"); 44 | 45 | io::CAN::CANStatus result; 46 | 47 | // Attempt to join the CAN network 48 | result = can.connect(); 49 | 50 | if (result != io::CAN::CANStatus::OK) { 51 | uart.printf("Failed to connect to the CAN network\r\n"); 52 | return 1; 53 | } 54 | 55 | uint8_t count = 0; 56 | while (true) { 57 | // Transmit every second 58 | payload[7] = count; 59 | transmit_message.setPayload(payload); 60 | result = can.transmit(transmit_message); 61 | if (result != io::CAN::CANStatus::OK) { 62 | uart.printf("Failed to transmit message\r\n"); 63 | return 1; 64 | } 65 | count++; 66 | 67 | time::wait(1000); 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /libs/HALf3/include/HALf3/stm32f3xx_it.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32f3xx_it.h 5 | * @brief This file contains the headers of the interrupt handlers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2021 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __STM32F3xx_IT_H 23 | #define __STM32F3xx_IT_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Private includes ----------------------------------------------------------*/ 30 | /* USER CODE BEGIN Includes */ 31 | 32 | /* USER CODE END Includes */ 33 | 34 | /* Exported types ------------------------------------------------------------*/ 35 | /* USER CODE BEGIN ET */ 36 | 37 | /* USER CODE END ET */ 38 | 39 | /* Exported constants --------------------------------------------------------*/ 40 | /* USER CODE BEGIN EC */ 41 | 42 | /* USER CODE END EC */ 43 | 44 | /* Exported macro ------------------------------------------------------------*/ 45 | /* USER CODE BEGIN EM */ 46 | 47 | /* USER CODE END EM */ 48 | 49 | /* Exported functions prototypes ---------------------------------------------*/ 50 | void NMI_Handler(void); 51 | void HardFault_Handler(void); 52 | void MemManage_Handler(void); 53 | void BusFault_Handler(void); 54 | void UsageFault_Handler(void); 55 | void SVC_Handler(void); 56 | void DebugMon_Handler(void); 57 | void PendSV_Handler(void); 58 | void SysTick_Handler(void); 59 | /* USER CODE BEGIN EFP */ 60 | 61 | /* USER CODE END EFP */ 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif /* __STM32F3xx_IT_H */ 68 | 69 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 70 | -------------------------------------------------------------------------------- /src/core/rtos/Mutex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::rtos { 4 | 5 | Mutex::Mutex(char* name, bool priorityInheritance) 6 | : Initializable(name), txMutex(), priorityInheritance(priorityInheritance) {} 7 | 8 | TXError Mutex::init(BytePoolBase& pool) { 9 | return static_cast(tx_mutex_create(&txMutex, name, (UINT) priorityInheritance)); 10 | } 11 | 12 | Mutex::~Mutex() { 13 | tx_mutex_delete(&txMutex); 14 | } 15 | 16 | TXError Mutex::get(uint32_t waitOption) { 17 | return static_cast(tx_mutex_get(&txMutex, waitOption)); 18 | } 19 | 20 | TXError Mutex::put() { 21 | return static_cast(tx_mutex_put(&txMutex)); 22 | } 23 | 24 | TXError Mutex::prioritize() { 25 | return static_cast(tx_mutex_prioritize(&txMutex)); 26 | } 27 | 28 | TXError Mutex::getOwnershipCount(uint32_t* ownershipCount) { 29 | uint32_t status = tx_mutex_info_get(&txMutex, nullptr, ownershipCount, nullptr, nullptr, nullptr, nullptr); 30 | return static_cast(status); 31 | } 32 | 33 | TXError Mutex::getNameOfOwner(char** ownerName) { 34 | TX_THREAD* owner; 35 | uint32_t status = tx_mutex_info_get(&txMutex, nullptr, nullptr, &owner, nullptr, nullptr, nullptr); 36 | // exit early if the call failed 37 | if (status != TXE_SUCCESS) { 38 | return static_cast(status); 39 | } 40 | 41 | // read the name off the struct 42 | status = tx_thread_info_get(owner, ownerName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); 43 | return static_cast(status); 44 | } 45 | 46 | TXError Mutex::getNameOfFirstSuspendedThread(char** threadName) { 47 | TX_THREAD* thread; 48 | uint32_t status = tx_mutex_info_get(&txMutex, nullptr, nullptr, nullptr, &thread, nullptr, nullptr); 49 | // exit early if the call failed 50 | if (status != TXE_SUCCESS) { 51 | return static_cast(status); 52 | } 53 | 54 | // read the name off the struct 55 | status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); 56 | return static_cast(status); 57 | } 58 | 59 | TXError Mutex::getNumSuspendedThreads(uint32_t* numSuspendedThreads) { 60 | uint32_t status = tx_mutex_info_get(&txMutex, nullptr, nullptr, nullptr, nullptr, numSuspendedThreads, nullptr); 61 | return static_cast(status); 62 | } 63 | 64 | } // namespace core::rtos 65 | -------------------------------------------------------------------------------- /samples/timer/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This sample will demo the basic functionality for the timer driver 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace io = core::io; 10 | namespace dev = core::dev; 11 | 12 | io::GPIO* ledGPIO; 13 | io::GPIO* interruptGPIO2Hz; 14 | io::GPIO* interruptGPIOStopStart; 15 | io::GPIO* reloadGPIO; 16 | 17 | void timer2IRQHandler(void* htim) { 18 | io::GPIO::State state = ledGPIO->readPin(); 19 | io::GPIO::State toggleState = state == io::GPIO::State::HIGH ? io::GPIO::State::LOW : io::GPIO::State::HIGH; 20 | ledGPIO->writePin(toggleState); 21 | interruptGPIO2Hz->writePin(toggleState); 22 | } 23 | 24 | void timer15IRQHandler(void* htim) { 25 | io::GPIO::State state = interruptGPIOStopStart->readPin(); 26 | io::GPIO::State toggleState = state == io::GPIO::State::HIGH ? io::GPIO::State::LOW : io::GPIO::State::HIGH; 27 | interruptGPIOStopStart->writePin(toggleState); 28 | } 29 | 30 | void timer16IRQHandler(void* htim) { 31 | io::GPIO::State state = reloadGPIO->readPin(); 32 | io::GPIO::State toggleState = state == io::GPIO::State::HIGH ? io::GPIO::State::LOW : io::GPIO::State::HIGH; 33 | reloadGPIO->writePin(toggleState); 34 | } 35 | 36 | int main() { 37 | // Initialize system 38 | core::platform::init(); 39 | 40 | // Setup GPIO 41 | ledGPIO = &io::getGPIO(); 42 | interruptGPIO2Hz = &io::getGPIO(io::GPIO::Direction::OUTPUT); 43 | interruptGPIOStopStart = &io::getGPIO(io::GPIO::Direction::OUTPUT); 44 | reloadGPIO = &io::getGPIO(io::GPIO::Direction::OUTPUT); 45 | 46 | // Setup the Timer 47 | dev::Timer& timer2 = dev::getTimer(500); 48 | // F4xx does not support Timers 15 & 16, change them to Timer11 & Timer12 49 | dev::Timer& timer15 = dev::getTimer(100); 50 | dev::Timer& timer16 = dev::getTimer(200); 51 | 52 | timer2.startTimer(timer2IRQHandler); 53 | timer15.startTimer(timer15IRQHandler); 54 | timer16.startTimer(timer16IRQHandler); 55 | 56 | while (1) { 57 | core::time::wait(500); 58 | timer15.stopTimer(); 59 | timer16.reloadTimer(); 60 | core::time::wait(500); 61 | timer15.startTimer(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /libs/HALf3/include/HALf3/stm32f3xx_hal_spi_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f3xx_hal_spi_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of SPI HAL Extended module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef STM32F3xx_HAL_SPI_EX_H 22 | #define STM32F3xx_HAL_SPI_EX_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32f3xx_hal_def.h" 30 | 31 | /** @addtogroup STM32F3xx_HAL_Driver 32 | * @{ 33 | */ 34 | 35 | /** @addtogroup SPIEx 36 | * @{ 37 | */ 38 | 39 | /* Exported types ------------------------------------------------------------*/ 40 | /* Exported constants --------------------------------------------------------*/ 41 | /* Exported macros -----------------------------------------------------------*/ 42 | /* Exported functions --------------------------------------------------------*/ 43 | /** @addtogroup SPIEx_Exported_Functions 44 | * @{ 45 | */ 46 | 47 | /* Initialization and de-initialization functions ****************************/ 48 | /* IO operation functions *****************************************************/ 49 | /** @addtogroup SPIEx_Exported_Functions_Group1 50 | * @{ 51 | */ 52 | HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(SPI_HandleTypeDef *hspi); 53 | /** 54 | * @} 55 | */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | /** 66 | * @} 67 | */ 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif /* STM32F3xx_HAL_SPI_EX_H */ 74 | 75 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 76 | -------------------------------------------------------------------------------- /include/core/io/platform/f4xx/GPIOf4xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_GPIOf4xx_ 2 | #define _EVT_GPIOf4xx_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace core::io { 10 | 11 | class GPIOf4xx : public GPIO { 12 | public: 13 | /** 14 | * Create an instance of the STMF4xx GPIO pin using the provided pin. The 15 | * direction will have to be set manually before use. 16 | * 17 | * @param[in] pin The pin for the GPIO instance to use. 18 | */ 19 | GPIOf4xx(Pin pin); 20 | 21 | /** 22 | * Create an instance of the STMF4xx GPIO pin using the provided pin 23 | * and direction. 24 | * 25 | * @param[in] pin The pin for the GPIO instance to use. 26 | * @param[in] direction The flow of data (either input or output). 27 | */ 28 | GPIOf4xx(Pin pin, Direction direction, Pull pull = Pull::PULL_DOWN); 29 | 30 | void setDirection(Direction direction) override; 31 | 32 | void writePin(State state) override; 33 | 34 | State readPin() override; 35 | 36 | void registerIRQ(TriggerEdge edge, void (*irqHandler)(GPIO* pin, void* priv), void* priv) override; 37 | 38 | /** 39 | * Condenses gpio settings initialization into a single function. 40 | * @param targetGpio gpio instance to initialize 41 | * @param pins array of pins used by gpio instance 42 | * @param numOfPins size of the pin array (either 1 or 2) 43 | * @param mode gpio configuration mode 44 | * @param pull pull-up or pull-down activation 45 | * @param speed maximum gpio output frequency 46 | * Possible values for Mode, Pull, and Speed can be found in "stm32f4xx_hal_gpio.h" 47 | * @param alternate gpio alternate function selection 48 | */ 49 | static void gpioStateInit(GPIO_InitTypeDef* targetGpio, Pin* pins, uint8_t numOfPins, uint32_t mode, uint32_t pull, 50 | uint32_t speed, uint8_t alternate = 0x0DU); 51 | 52 | private: 53 | // See stm32f4xx_hal_gpio -> GPIO_mode for info on derivations 54 | constexpr static int GPIO_MODE_IT_SHIFT = 20; 55 | constexpr static uint32_t GPIO_TRIGGER_INTERRUPT_BASE = GPIO_MODE_IT_RISING & ~(1 << GPIO_MODE_IT_SHIFT); 56 | 57 | /// Pin representing the underlying HAL pin identifer 58 | uint16_t halPin; 59 | /// Represents the GPIO port of the pin (A, B, C, D, E, or F) 60 | GPIO_TypeDef* port; 61 | }; 62 | 63 | } // namespace core::io 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'EVT-core' 21 | copyright = '2021, EVT' 22 | author = 'EVT' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | with open('../../version.txt') as version_file: 26 | version = version_file.readlines()[0] 27 | release = version 28 | 29 | 30 | # -- General configuration --------------------------------------------------- 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = [ 36 | 'breathe', 37 | 'sphinx_rtd_theme' 38 | ] 39 | 40 | # Add any paths that contain templates here, relative to this directory. 41 | templates_path = ['_templates'] 42 | 43 | # List of patterns, relative to source directory, that match files and 44 | # directories to ignore when looking for source files. 45 | # This pattern also affects html_static_path and html_extra_path. 46 | exclude_patterns = [] 47 | 48 | 49 | # -- Options for HTML output ------------------------------------------------- 50 | 51 | # The theme to use for HTML and HTML Help pages. See the documentation for 52 | # a list of builtin themes. 53 | # 54 | html_theme = 'sphinx_rtd_theme' 55 | 56 | # Add any paths that contain custom static files (such as style sheets) here, 57 | # relative to this directory. They are copied after the builtin static files, 58 | # so a file named "default.css" will overwrite the builtin "default.css". 59 | html_static_path = ['_static'] 60 | 61 | 62 | # -- Doxygen support ---- # 63 | os.system('mkdir -p ../build/doxygen') 64 | breathe_default_project = 'EVT-core' 65 | breathe_projects = { 'EVT-core': '../build/doxygen/xml/' } 66 | os.system('cd ../; doxygen') 67 | -------------------------------------------------------------------------------- /include/core/io/platform/f3xx/GPIOf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_GPIOf3xx_ 2 | #define _EVT_GPIOf3xx_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace core::io { 10 | 11 | class GPIOf3xx : public GPIO { 12 | public: 13 | /** 14 | * Create an instance of the STMF3xx GPIO pin using the provided pin. The 15 | * direction will have to be set manually before use. 16 | * 17 | * @param[in] pin The pin for the GPIO instance to use. 18 | */ 19 | GPIOf3xx(Pin pin); 20 | 21 | /** 22 | * Create an instance of the STMF3xx GPIO pin using the provided pin 23 | * and direction. 24 | * 25 | * @param[in] pin The pin for the GPIO instance to use. 26 | * @param[in] direction The flow of data (either input or output). 27 | * @param[in] pull The direction of the internal pull resistor 28 | */ 29 | GPIOf3xx(Pin pin, Direction direction, Pull pull = Pull::PULL_DOWN); 30 | 31 | void setDirection(Direction direction) override; 32 | 33 | void writePin(State state) override; 34 | 35 | State readPin() override; 36 | 37 | void registerIRQ(TriggerEdge edge, void (*irqHandler)(GPIO* pin, void* priv), void* priv) override; 38 | 39 | /** 40 | * Condenses gpio settings initialization into a single function. 41 | * @param targetGpio gpio instance to initialize 42 | * @param pins array of pins used by gpio instance 43 | * @param numOfPins size of the pin array (either 1 or 2) 44 | * @param mode gpio configuration mode 45 | * @param pull pull-up or pull-down activation 46 | * @param speed maximum gpio output frequency 47 | * Possible values for Mode, Pull, and Speed can be found in "stm32f3xx_hal_gpio.h" 48 | * @param alternate gpio alternate function selection 49 | */ 50 | static void gpioStateInit(GPIO_InitTypeDef* targetGpio, Pin* pins, uint8_t numOfPins, uint32_t mode, uint32_t pull, 51 | uint32_t speed, uint8_t alternate = 0x0DU); 52 | 53 | private: 54 | // See stm32f3xx_hal_gpio -> GPIO_mode for info on derivations 55 | constexpr static int GPIO_MODE_IT_SHIFT = 20; 56 | 57 | constexpr static uint32_t GPIO_TRIGGER_INTERRUPT_BASE = GPIO_MODE_IT_RISING & ~(1 << GPIO_MODE_IT_SHIFT); 58 | 59 | /// Pin representing the underlying HAL pin identifer 60 | uint16_t halPin; 61 | /// Represents the GPIO port of the pin (A, B, C, D, E, or F) 62 | GPIO_TypeDef* port; 63 | }; 64 | 65 | } // namespace core::io 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /.vscode/settings.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "actionButtons": { 3 | "defaultColor": "statusBar.foreground", 4 | "reloadButton": "$(refresh)", 5 | "loadNpmCommands": false, 6 | "inheritGlobalCommands": true, 7 | "commands": [ 8 | { 9 | "name": "$(trash) Clean", 10 | "tooltip": "Perform a CMAKE clean on the current preset", 11 | "command":"workbench.action.tasks.runTask", 12 | "args": ["CMake: clean"], 13 | "useVsCodeApi": true 14 | }, 15 | { 16 | "name": "$(tools) Build", 17 | "tooltip": "Build the preset", 18 | "command":"workbench.action.tasks.runTask", 19 | "args": ["CMake: build"], 20 | "useVsCodeApi": true 21 | }, 22 | { 23 | "name": "$(debug-alt) Debug", 24 | "tooltip": "Flash code and start debugging", 25 | "command":"workbench.action.tasks.runTask", 26 | "args": ["flash debug"], 27 | "useVsCodeApi": true 28 | }, 29 | { 30 | "name": "$(play) Run", 31 | "tooltip": "Flash code", 32 | "command":"workbench.action.tasks.runTask", 33 | "args": ["Flash project"], 34 | "useVsCodeApi": true 35 | } 36 | ] 37 | }, 38 | "editor.tokenColorCustomizations": { 39 | "textMateRules": [ 40 | { 41 | "scope": "markup.other.log.error", 42 | "settings": { 43 | "foreground": "#FF0000" 44 | } 45 | }, 46 | { 47 | "scope": "markup.other.log.warn", 48 | "settings": { 49 | "foreground": "#c500f7cc" 50 | } 51 | }, 52 | { 53 | "scope": "markup.other.log.info", 54 | "settings": { 55 | "foreground": "#2cd3c5" 56 | } 57 | }, 58 | { 59 | "scope": "markup.other.log.debug", 60 | "settings": { 61 | "foreground": "#888585" 62 | } 63 | }, 64 | { 65 | "scope": "markup.other.log.highlight", 66 | "settings": { 67 | "foreground": "#19ff04" 68 | } 69 | } 70 | ] 71 | } 72 | } -------------------------------------------------------------------------------- /libs/HALf4/include/HALf4/stm32f4xx_hal_flash_ramfunc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f4xx_hal_flash_ramfunc.h 4 | * @author MCD Application Team 5 | * @brief Header file of FLASH RAMFUNC driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2017 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file in 13 | * the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | ****************************************************************************** 16 | */ 17 | 18 | /* Define to prevent recursive inclusion -------------------------------------*/ 19 | #ifndef __STM32F4xx_FLASH_RAMFUNC_H 20 | #define __STM32F4xx_FLASH_RAMFUNC_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F412Zx) ||\ 26 | defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32f4xx_hal_def.h" 30 | 31 | /** @addtogroup STM32F4xx_HAL_Driver 32 | * @{ 33 | */ 34 | 35 | /** @addtogroup FLASH_RAMFUNC 36 | * @{ 37 | */ 38 | 39 | /* Exported types ------------------------------------------------------------*/ 40 | /* Exported macro ------------------------------------------------------------*/ 41 | /* Exported functions --------------------------------------------------------*/ 42 | /** @addtogroup FLASH_RAMFUNC_Exported_Functions 43 | * @{ 44 | */ 45 | 46 | /** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group1 47 | * @{ 48 | */ 49 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_StopFlashInterfaceClk(void); 50 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_StartFlashInterfaceClk(void); 51 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EnableFlashSleepMode(void); 52 | __RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_DisableFlashSleepMode(void); 53 | /** 54 | * @} 55 | */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | /** 66 | * @} 67 | */ 68 | 69 | #endif /* STM32F410xx || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */ 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | 75 | #endif /* __STM32F4xx_FLASH_RAMFUNC_H */ 76 | 77 | -------------------------------------------------------------------------------- /src/core/rtos/EventFlags.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace core::rtos { 4 | 5 | EventFlags::EventFlags(char* name) : Initializable(name), txEventFlagsGroup() {} 6 | 7 | TXError EventFlags::init(core::rtos::BytePoolBase& pool) { 8 | return static_cast(tx_event_flags_create(&txEventFlagsGroup, name)); 9 | } 10 | 11 | EventFlags::~EventFlags() { 12 | tx_event_flags_delete(&txEventFlagsGroup); 13 | } 14 | 15 | TXError EventFlags::set(uint32_t mask) { 16 | return static_cast(tx_event_flags_set(&txEventFlagsGroup, mask, TX_OR)); 17 | } 18 | 19 | TXError EventFlags::clear(uint32_t mask) { 20 | return static_cast(tx_event_flags_set(&txEventFlagsGroup, ~mask, TX_AND)); 21 | } 22 | 23 | TXError EventFlags::get(uint32_t mask, bool waitForAllFlags, bool clear, uint32_t waitOption, uint32_t* output) { 24 | // ThreadX packs waitForAllFlags and clear into one uint32_t option where the first bit is whether to clear, 25 | // and the second bit is whether to wait. 26 | uint32_t option = ((uint32_t) waitForAllFlags << 1) | ((uint32_t) clear); 27 | return static_cast(tx_event_flags_get(&txEventFlagsGroup, mask, option, output, waitOption)); 28 | } 29 | 30 | TXError EventFlags::registerNotifyFunction(void (*notifyFunction)(EventFlags*)) { 31 | // todo: registerNotifyFunction must be implemented 32 | return TXE_FEATURE_NOT_ENABLED; 33 | } 34 | 35 | TXError EventFlags::getCurrentFlags(uint32_t* flags) { 36 | uint32_t status = tx_event_flags_info_get(&txEventFlagsGroup, nullptr, flags, nullptr, nullptr, nullptr); 37 | return static_cast(status); 38 | } 39 | 40 | TXError EventFlags::getNameOfFirstSuspendedThread(char** threadName) { 41 | // grab a pointer to the first suspended thread struct 42 | TX_THREAD* thread; 43 | uint32_t status = tx_event_flags_info_get(&txEventFlagsGroup, nullptr, nullptr, &thread, nullptr, nullptr); 44 | 45 | // exit early if the call failed 46 | if (status != TXE_SUCCESS) { 47 | return static_cast(status); 48 | } 49 | 50 | // read the name off the struct 51 | status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); 52 | 53 | return static_cast(status); 54 | } 55 | 56 | TXError EventFlags::getNumSuspendedThreads(uint32_t* numSuspendedThreads) { 57 | uint32_t status = 58 | tx_event_flags_info_get(&txEventFlagsGroup, nullptr, nullptr, nullptr, numSuspendedThreads, nullptr); 59 | return static_cast(status); 60 | } 61 | 62 | } // namespace core::rtos 63 | -------------------------------------------------------------------------------- /samples/lcd/basic/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample code for showing all capabilities of an LCD. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace dev = core::dev; 13 | namespace io = core::io; 14 | namespace time = core::time; 15 | 16 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; 17 | 18 | constexpr uint8_t deviceCount = 1; 19 | 20 | io::GPIO* devices[deviceCount]; 21 | 22 | int main() { 23 | // Initialize system 24 | core::platform::init(); 25 | 26 | // Setup UART 27 | io::UART& uart = io::getUART(9600); 28 | 29 | // Uses HUDL 1.0 Pins 30 | io::GPIO& regSelect = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 31 | io::GPIO& reset = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 32 | 33 | devices[0] = &io::getGPIO(core::io::GPIO::Direction::OUTPUT); 34 | devices[0]->writePin(io::GPIO::State::HIGH); 35 | 36 | // Setup SPI 37 | io::SPI& spi = io::getSPI(devices, deviceCount); 38 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE0, SPI_MSB_FIRST); 39 | 40 | // Sets up LCD 41 | uart.printf("Creating LCD Object...\n\r"); 42 | core::dev::LCD lcd(regSelect, reset, spi); 43 | uart.printf("Initializing LCD...\n\r"); 44 | lcd.initLCD(); 45 | lcd.clearLCD(); 46 | 47 | const char* text = 48 | R"( !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~)"; 49 | lcd.writeText(text, 0, 0, core::dev::LCD::SMALL, true); 50 | 51 | uint8_t ball[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 52 | uint8_t col = 0; 53 | uint8_t page = 4; 54 | 55 | lcd.displayBitMapInArea(ball, 8, 1, page, col); 56 | 57 | uint8_t number = 0; 58 | 59 | while (true) { 60 | lcd.clearArea(8, 1, page, col); 61 | 62 | col++; 63 | if (col >= 128) { 64 | col = 0; 65 | page++; 66 | 67 | if (page > 6) { 68 | page = 4; 69 | } 70 | } 71 | 72 | lcd.displayBitMapInArea(ball, 8, 1, page, col); 73 | 74 | lcd.clearArea(16, 1, 7, 0); 75 | 76 | char buffer[128] = {}; 77 | snprintf(buffer, (8), "%d", (number)); 78 | lcd.writeText(buffer, 7, 0, core::dev::LCD::SMALL, true); 79 | 80 | number++; 81 | time::wait(500); 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | # This file defines a GitHub Workflow which is used to test building EVT-Core and other EVT code. 2 | # When a pull request is made to the main branch, this Workflow will be automatically run on the 3 | # requested changes to ensure the repository still builds successfully and all files fit the team's 4 | # formatting standard. This workflow is designed to work only on a linux server. 5 | name: CMake 6 | 7 | # Define the workflow's triggers 8 | on: 9 | pull_request: 10 | branches: [main] 11 | 12 | # Set necessary environment variables 13 | env: 14 | GCC_ARM_TOOLS_PATH: /usr/bin 15 | 16 | jobs: 17 | build: 18 | # Select the server's operating system 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | # Checkout the repository, including all submodules 23 | - name: Checkout Repository 24 | uses: actions/checkout@v2 25 | with: 26 | ref: ${{ github.event.pull_request.head.ref }} 27 | submodules: recursive 28 | 29 | # Install the gcc-arm tools and clang-format, and ensure clang-format 12 is being used 30 | - name: Install Compiler and Linter 31 | run: | 32 | sudo apt-get install gcc-arm-none-eabi 33 | sudo apt-get install clang-format-15 34 | sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-15 10000 35 | 36 | # Build the code for all supported chips 37 | - name: F302 Build 38 | run: | 39 | cmake -DTARGET_DEV=STM32F302x8 -B ${{github.workspace}}/build 40 | cmake --build ${{github.workspace}}/build 41 | 42 | - name: F334 Build 43 | run: | 44 | cmake -DTARGET_DEV=STM32F334x8 -B ${{github.workspace}}/build 45 | cmake --build ${{github.workspace}}/build 46 | 47 | - name: F446 Build 48 | run: | 49 | cmake -DTARGET_DEV=STM32F446xx -B ${{github.workspace}}/build 50 | # cmake --build ${{github.workspace}}/build 51 | # Apply clang-format formatting to the branch and create a new commit if any files are changed 52 | - name: Apply Formatting 53 | run: | 54 | cmake --build ${{github.workspace}}/build --target clang-format 55 | if git diff-files --quiet; then 56 | echo 'No formatting changes' 57 | else 58 | echo 'Formatting changes applied:' 59 | git diff --raw 60 | git config --global user.email "N/A" 61 | git config --global user.name "GitHub Build" 62 | git commit -a -m "Applied Formatting Changes During GitHub Build" 63 | git push origin 64 | fi 65 | -------------------------------------------------------------------------------- /src/core/utils/log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace io = core::io; 6 | 7 | namespace core::log { 8 | /** 9 | * Set the UART to be used for logging 10 | * 11 | * @param uart[in] UART to be used for logging 12 | */ 13 | void Logger::setUART(io::UART* loggingUART) { 14 | #ifdef EVT_CORE_LOG_ENABLE 15 | uart = loggingUART; 16 | #endif 17 | } 18 | 19 | /** 20 | * Set the minimum log level to be displayed by the logger 21 | * 22 | * @param level[in] Minimum log level to be displayed by the logger 23 | */ 24 | void Logger::setLogLevel(Logger::LogLevel level) { 25 | #ifdef EVT_CORE_LOG_ENABLE 26 | minLevel = level; 27 | #endif 28 | } 29 | 30 | /** 31 | * Set the clock to be used for timestamps 32 | * 33 | * @param rtc Clock to be used for timestamps 34 | */ 35 | void Logger::setClock(dev::RTC* rtc) { 36 | #ifdef EVT_CORE_LOG_ENABLE 37 | clock = rtc; 38 | #endif 39 | } 40 | 41 | /** 42 | * Write the formatted string to the serial logger if the logger log level 43 | * reaches this level 44 | * 45 | * @param level[in] Log level of this statement 46 | * @param format[in] Format string to be logged 47 | * @param ...[in] Variables to be formatted into the log statement 48 | */ 49 | void Logger::log(LogLevel level, const char* format, ...) { 50 | #ifdef EVT_CORE_LOG_ENABLE 51 | // If there isn't a UART interface, cannot print 52 | // If the level of this statement is less than the logger's minLevel, 53 | // shouldn't print 54 | if (!uart || level < minLevel) 55 | return; 56 | 57 | // If the clock has been set, print the timestamp 58 | if (clock) { 59 | uint32_t time = clock->getTime(); 60 | uart->printf("%d ", time); 61 | } 62 | 63 | // Print the level of this log statement 64 | switch (level) { 65 | case LogLevel::DEBUG: 66 | uart->printf("DEBUG::"); 67 | break; 68 | case LogLevel::INFO: 69 | uart->printf("INFO::"); 70 | break; 71 | case LogLevel::WARNING: 72 | uart->printf("WARNING::"); 73 | break; 74 | case LogLevel::ERROR: 75 | uart->printf("ERROR::"); 76 | break; 77 | } 78 | 79 | // Initialize variable argument list 80 | va_list args; 81 | va_start(args, format); 82 | 83 | // Apply print formatting from the variable argument list to format and 84 | // print it 85 | char logString[200]; 86 | vsprintf(logString, format, args); 87 | uart->printf("%s\r\n", logString); 88 | 89 | // Closes the variable argument list 90 | va_end(args); 91 | #endif 92 | } 93 | 94 | Logger LOGGER; 95 | } // namespace core::log 96 | -------------------------------------------------------------------------------- /samples/lcd/lcd-segment/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample code for displaying a segmented display on an LCD. 3 | */ 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace dev = core::dev; 14 | namespace io = core::io; 15 | namespace time = core::time; 16 | 17 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; 18 | 19 | constexpr uint8_t deviceCount = 1; 20 | 21 | io::GPIO* devices[deviceCount]; 22 | 23 | int main() { 24 | // Initialize system 25 | core::platform::init(); 26 | 27 | // Setup UART 28 | io::UART& uart = io::getUART(9600); 29 | 30 | // Uses HUDL 1.0 Pins 31 | io::GPIO& regSelect = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 32 | io::GPIO& reset = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 33 | 34 | devices[0] = &io::getGPIO(core::io::GPIO::Direction::OUTPUT); 35 | devices[0]->writePin(io::GPIO::State::HIGH); 36 | 37 | // Setup SPI 38 | io::SPI& spi = io::getSPI(devices, deviceCount); 39 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE0, SPI_MSB_FIRST); 40 | 41 | // Sets up LCD 42 | uart.printf("Creating LCD Object...\n\r"); 43 | core::dev::LCD lcd(regSelect, reset, spi); 44 | uart.printf("Initializing LCD...\n\r"); 45 | lcd.initLCD(); 46 | lcd.clearLCD(); 47 | 48 | // The segment titles 49 | char* titles[9] = { 50 | (char*) "B Voltage", 51 | (char*) "Speed", 52 | (char*) "RPM", 53 | (char*) "Temp 1", 54 | (char*) "Temp 2", 55 | (char*) "Temp 3", 56 | (char*) "Status 1", 57 | (char*) "PVC Stat", 58 | (char*) "Torque", 59 | }; 60 | lcd.setDefaultSections(titles); 61 | 62 | // Set the default 63 | lcd.displaySectionHeaders(); 64 | lcd.setTextForSection(0, "3.2 v"); 65 | lcd.setTextForSection(2, "25 MPH"); 66 | lcd.setTextForSection(2, "3000"); 67 | lcd.setTextForSection(3, "40 C"); 68 | lcd.setTextForSection(4, "44 C"); 69 | lcd.setTextForSection(5, "43 C"); 70 | lcd.setTextForSection(6, "ON"); 71 | lcd.setTextForSection(7, "Ready"); 72 | lcd.setTextForSection(8, "100 NM"); 73 | 74 | uint8_t number = 0; 75 | 76 | while (true) { 77 | char buffer[128] = {}; 78 | snprintf(buffer, (8), "%d", (number)); 79 | lcd.setTextForSection(1, buffer); 80 | 81 | number++; 82 | time::wait(500); 83 | } 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /samples/canopen/canopen_sample/arduino_canopen/arduino_canopen.ino: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include 5 | 6 | //#define CS_PIN 9 //CAN shield v2 7 | #define CS_PIN 10 //CAN shield v1.4 8 | #define IRQ_PIN 2 9 | 10 | bool readyToSend = true; 11 | int counter = 0; 12 | long timeSinceLastReceive = 0; 13 | 14 | void onReceive(int packetSize) { 15 | if(CAN.packetId() != 0x181) 16 | return; 17 | 18 | long timeDelta = millis() - timeSinceLastReceive; 19 | timeSinceLastReceive = millis(); 20 | 21 | // received a packet 22 | Serial.print("Received "); 23 | 24 | if (CAN.packetExtended()) { 25 | Serial.print("extended "); 26 | } 27 | 28 | if (CAN.packetRtr()) { 29 | // Remote transmission request, packet contains no data 30 | Serial.print("RTR "); 31 | } 32 | 33 | Serial.print("packet with id 0x"); 34 | Serial.print(CAN.packetId(), HEX); 35 | 36 | if (CAN.packetRtr()) { 37 | Serial.print(" and requested length "); 38 | Serial.println(CAN.packetDlc()); 39 | } else { 40 | Serial.print(" and length "); 41 | Serial.print(packetSize); 42 | 43 | Serial.print(" and time delta "); 44 | Serial.println(timeDelta); 45 | 46 | // only print packet data for non-RTR packets 47 | while (CAN.available()) { 48 | Serial.print(" "); 49 | Serial.print(CAN.read(), HEX); 50 | } 51 | Serial.println(); 52 | } 53 | 54 | Serial.println(); 55 | 56 | readyToSend = true; 57 | } 58 | 59 | void setup() { 60 | Serial.begin(9600); 61 | while (!Serial); 62 | 63 | Serial.println("CAN Sender"); 64 | 65 | CAN.setPins(CS_PIN, IRQ_PIN); 66 | // start the CAN bus at 500 kbps 67 | if (!CAN.begin(500E3)) { 68 | Serial.println("Starting CAN failed!"); 69 | while (1); 70 | } 71 | 72 | // register the receive callback 73 | CAN.onReceive(onReceive); 74 | } 75 | 76 | void loop() { 77 | //Serial.print("Sending CAN message "); 78 | 79 | CAN.beginPacket(0x601); 80 | 81 | // Command byte 82 | CAN.write(0x2F); 83 | 84 | // Index access 85 | CAN.write(0x00); 86 | CAN.write(0x21); 87 | 88 | // Subindex 89 | CAN.write(0x00); 90 | 91 | // Data 92 | CAN.write(counter); 93 | CAN.write(0x00); 94 | CAN.write(0x00); 95 | CAN.write(0x05); 96 | 97 | CAN.endPacket(); 98 | 99 | readyToSend = false; 100 | 101 | counter++; 102 | if(counter > 100) 103 | counter = 0; 104 | 105 | delay(500); 106 | // Serial.println("done"); 107 | } 108 | -------------------------------------------------------------------------------- /samples/can/loopback/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Basic example of using CAN. In this situation the device is setup in 3 | * loopback so that the CAN messages can be sent and received to itself. 4 | * 5 | * @author Collin Bolles 6 | */ 7 | #include 8 | #include 9 | #include 10 | 11 | namespace io = core::io; 12 | namespace time = core::time; 13 | 14 | int main() { 15 | // Initialize system 16 | core::platform::init(); 17 | 18 | // Get CAN instance with loopback enabled 19 | io::CAN& can = io::getCAN(true); 20 | io::UART& uart = io::getUART(9600); 21 | 22 | uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xBE, 0xEF, 0x00, 0x01, 0x02}; 23 | io::CANMessage transmit_message(0b00010011110, 8, &payload[0], false); 24 | io::CANMessage received_message; 25 | 26 | io::CAN::CANStatus result; 27 | 28 | // Attempt to join the CAN network 29 | result = can.connect(); 30 | 31 | // can.addCANFilter(0, 0, 13); //This would create a filter that allows all messages through 32 | can.addCANFilter(0b00000011010, 0b0000111111100000, 2); 33 | can.addCANFilter(0b00001010111, 0b0000111111100000, 3); 34 | can.enableEmergencyFilter(ENABLE); 35 | 36 | uart.printf("Starting CAN testing\r\n"); 37 | 38 | if (result != io::CAN::CANStatus::OK) { 39 | uart.printf("Failed to connect to CAN network\r\n"); 40 | return 1; 41 | } 42 | 43 | while (true) { 44 | result = can.transmit(transmit_message); 45 | if (result != io::CAN::CANStatus::OK) { 46 | uart.printf("Failed to transmit message\r\n"); 47 | return 1; 48 | } 49 | 50 | result = can.receive(&received_message, false); 51 | if (result != io::CAN::CANStatus::OK) { 52 | uart.printf("Failed to receive message\r\n"); 53 | continue; 54 | } 55 | 56 | if (received_message.getDataLength() == 0) { 57 | uart.printf("Message filtered out!"); 58 | } else { 59 | uart.printf("Message received\r\n"); 60 | uart.printf("Message id: %d \r\n", received_message.getId()); 61 | uart.printf("Message length: %d\r\n", received_message.getDataLength()); 62 | uart.printf("Message contents: "); 63 | 64 | uint8_t* message_payload = received_message.getPayload(); 65 | for (int i = 0; i < received_message.getDataLength(); i++) { 66 | uart.printf("0x%02X ", message_payload[i]); 67 | } 68 | } 69 | uart.printf("\r\n\r\n"); 70 | 71 | time::wait(2000); 72 | } 73 | 74 | return 0; 75 | } -------------------------------------------------------------------------------- /samples/canopen/canopen_rpdo/arduino_tpdo/arduino_tpdo.ino: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include 5 | 6 | //#define CS_PIN 9 //CAN shield v2 7 | #define CS_PIN 10 //CAN shield v1.4 8 | #define IRQ_PIN 2 9 | 10 | uint8_t counter1 = 0; 11 | uint16_t counter2 = 0; 12 | long timeSinceLastReceive = 0; 13 | long lastSend = 0; 14 | 15 | void onReceive(int packetSize) { 16 | if(CAN.packetId() != 0x180) 17 | return; 18 | 19 | long timeDelta = millis() - timeSinceLastReceive; 20 | timeSinceLastReceive = millis(); 21 | 22 | // received a packet 23 | Serial.print("Received "); 24 | 25 | if (CAN.packetExtended()) { 26 | Serial.print("extended "); 27 | } 28 | 29 | if (CAN.packetRtr()) { 30 | // Remote transmission request, packet contains no data 31 | Serial.print("RTR "); 32 | } 33 | 34 | Serial.print("packet with id 0x"); 35 | Serial.print(CAN.packetId(), HEX); 36 | 37 | if (CAN.packetRtr()) { 38 | Serial.print(" and requested length "); 39 | Serial.println(CAN.packetDlc()); 40 | } else { 41 | Serial.print(" and length "); 42 | Serial.print(packetSize); 43 | 44 | Serial.print(" and time delta "); 45 | Serial.println(timeDelta); 46 | 47 | // only print packet data for non-RTR packets 48 | while (CAN.available()) { 49 | Serial.print(" "); 50 | Serial.print(CAN.read(), HEX); 51 | } 52 | Serial.println(); 53 | } 54 | 55 | Serial.println(); 56 | } 57 | 58 | void setup() { 59 | Serial.begin(9600); 60 | while (!Serial); 61 | 62 | Serial.println("CAN Sender"); 63 | 64 | CAN.setPins(CS_PIN, IRQ_PIN); 65 | // start the CAN bus at 500 kbps 66 | if (!CAN.begin(500E3)) { 67 | Serial.println("Starting CAN failed!"); 68 | while (1); 69 | } 70 | 71 | // register the receive callback 72 | CAN.onReceive(onReceive); 73 | } 74 | 75 | void loop() { 76 | //Serial.print("Sending CAN message "); 77 | 78 | if(lastSend + 1000 < millis()){ 79 | lastSend = millis(); 80 | 81 | Serial.print("Sending CAN message: "); 82 | Serial.print(counter1, HEX); 83 | Serial.print(" "); 84 | Serial.println(counter2, HEX); 85 | 86 | //manually create TPDO message 87 | CAN.beginPacket(0x181); 88 | CAN.write(counter1); 89 | CAN.write((uint8_t)(counter2 & 0x00FF)); 90 | CAN.write((uint8_t)(counter2 >> 8)); 91 | CAN.endPacket(); 92 | } 93 | 94 | counter1++; 95 | if(counter1 % 10 == 0){ 96 | counter2 = (counter2+1)*3; 97 | } 98 | 99 | delay(10); 100 | } 101 | -------------------------------------------------------------------------------- /libs/HALf4/include/HALf4/stm32f4xx_hal_ltdc_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f4xx_hal_ltdc_ex.h 4 | * @author MCD Application Team 5 | * @brief Header file of LTDC HAL Extension module. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef STM32F4xx_HAL_LTDC_EX_H 21 | #define STM32F4xx_HAL_LTDC_EX_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | #include "stm32f4xx_hal_def.h" 29 | 30 | #if defined (LTDC) && defined (DSI) 31 | 32 | #include "stm32f4xx_hal_dsi.h" 33 | 34 | /** @addtogroup STM32F4xx_HAL_Driver 35 | * @{ 36 | */ 37 | 38 | /** @addtogroup LTDCEx 39 | * @{ 40 | */ 41 | 42 | /* Exported types ------------------------------------------------------------*/ 43 | /* Exported constants --------------------------------------------------------*/ 44 | /* Exported macro ------------------------------------------------------------*/ 45 | /* Exported functions --------------------------------------------------------*/ 46 | /** @addtogroup LTDCEx_Exported_Functions 47 | * @{ 48 | */ 49 | 50 | /** @addtogroup LTDCEx_Exported_Functions_Group1 51 | * @{ 52 | */ 53 | HAL_StatusTypeDef HAL_LTDCEx_StructInitFromVideoConfig(LTDC_HandleTypeDef *hltdc, DSI_VidCfgTypeDef *VidCfg); 54 | HAL_StatusTypeDef HAL_LTDCEx_StructInitFromAdaptedCommandConfig(LTDC_HandleTypeDef *hltdc, DSI_CmdCfgTypeDef *CmdCfg); 55 | /** 56 | * @} 57 | */ 58 | 59 | /** 60 | * @} 61 | */ 62 | 63 | /* Private types -------------------------------------------------------------*/ 64 | /* Private variables ---------------------------------------------------------*/ 65 | /* Private constants ---------------------------------------------------------*/ 66 | /* Private macros ------------------------------------------------------------*/ 67 | /* Private functions ---------------------------------------------------------*/ 68 | 69 | /** 70 | * @} 71 | */ 72 | 73 | /** 74 | * @} 75 | */ 76 | 77 | #endif /* LTDC && DSI */ 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* STM32F4xx_HAL_LTDC_EX_H */ 84 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "configurePresets": [ 4 | { 5 | "name": "stm32f302-preset", 6 | "displayName": "STM32F302x8 Build", 7 | "description": "Configures the build for an STM32F302x8 target using the ARM GCC toolchain and Ninja.", 8 | "generator": "Ninja", 9 | "binaryDir": "${sourceDir}/build/${presetName}", 10 | "cacheVariables": { 11 | "CMAKE_BUILD_TYPE": "Debug", 12 | "EVT_CORE_LOG_ENABLE": "1", 13 | "TARGET_DEV": "STM32F302x8", 14 | "FORCE_COLORED_OUTPUT": "1" 15 | } 16 | }, 17 | { 18 | "name": "stm32f334-preset", 19 | "displayName": "STM32F334x8 Build", 20 | "description": "Configures the build for an STM32F334x8 target using the ARM GCC toolchain and Ninja.", 21 | "generator": "Ninja", 22 | "binaryDir": "${sourceDir}/build/${presetName}", 23 | "cacheVariables": { 24 | "CMAKE_BUILD_TYPE": "Debug", 25 | "EVT_CORE_LOG_ENABLE": "1", 26 | "TARGET_DEV": "STM32F334x8", 27 | "FORCE_COLORED_OUTPUT": "1" 28 | } 29 | }, 30 | { 31 | "name": "stm32f446-preset", 32 | "displayName": "STM32F446xx Build", 33 | "description": "Configures the build for an STM32F446xx target using the ARM GCC toolchain and Ninja.", 34 | "generator": "Ninja", 35 | "binaryDir": "${sourceDir}/build/${presetName}", 36 | "cacheVariables": { 37 | "CMAKE_BUILD_TYPE": "Debug", 38 | "EVT_CORE_LOG_ENABLE": "1", 39 | "TARGET_DEV": "STM32F446xx", 40 | "FORCE_COLORED_OUTPUT": "1" 41 | } 42 | }, 43 | { 44 | "name": "stm32f446-rtos-preset", 45 | "displayName": "STM32F446xx Build (RTOS)", 46 | "description": "Configures the build for an STM32F446xx target with RTOS support using the ARM GCC toolchain and Ninja.", 47 | "generator": "Ninja", 48 | "binaryDir": "${sourceDir}/build/${presetName}", 49 | "cacheVariables": { 50 | "CMAKE_BUILD_TYPE": "Debug", 51 | "EVT_CORE_LOG_ENABLE": true, 52 | "TARGET_DEV": "STM32F446xx", 53 | "FORCE_COLORED_OUTPUT": true, 54 | "USE_RTOS": true 55 | } 56 | } 57 | ], 58 | "buildPresets": [ 59 | { 60 | "name": "stm32f302-build", 61 | "configurePreset": "stm32f302-preset", 62 | "displayName": "Build for STM32F302" 63 | }, 64 | { 65 | "name": "stm32f334-build", 66 | "configurePreset": "stm32f334-preset", 67 | "displayName": "Build for STM32F334" 68 | }, 69 | { 70 | "name": "stm32f446-build", 71 | "configurePreset": "stm32f446-preset", 72 | "displayName": "Build for STM32F446" 73 | }, 74 | { 75 | "name": "stm32f446-rtos-build", 76 | "configurePreset": "stm32f446-rtos-preset", 77 | "displayName": "Build for STM32F446 (RTOS)" 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /samples/lcd/lcd-more-sections/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample code for display data on an LCD with more than the default sections 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace dev = core::dev; 13 | namespace io = core::io; 14 | namespace time = core::time; 15 | 16 | constexpr uint32_t SPI_SPEED = SPI_SPEED_500KHZ; 17 | 18 | constexpr uint8_t deviceCount = 1; 19 | 20 | io::GPIO* devices[deviceCount]; 21 | 22 | int main() { 23 | // Initialize system 24 | core::platform::init(); 25 | 26 | // Setup UART 27 | io::UART& uart = io::getUART(9600); 28 | 29 | // Uses HUDL 1.0 Pins 30 | io::GPIO& regSelect = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 31 | io::GPIO& reset = io::getGPIO(core::io::GPIO::Direction::OUTPUT); 32 | 33 | devices[0] = &io::getGPIO(core::io::GPIO::Direction::OUTPUT); 34 | devices[0]->writePin(io::GPIO::State::HIGH); 35 | 36 | // Setup SPI 37 | io::SPI& spi = io::getSPI(devices, deviceCount); 38 | spi.configureSPI(SPI_SPEED, io::SPI::SPIMode::SPI_MODE0, SPI_MSB_FIRST); 39 | 40 | // Sets up LCD 41 | uart.printf("Creating LCD Object...\n\r"); 42 | core::dev::LCD lcd(regSelect, reset, spi, 12, 3); 43 | uart.printf("Initializing LCD...\n\r"); 44 | lcd.initLCD(); 45 | lcd.clearLCD(); 46 | 47 | // The segment titles 48 | char* titles[12] = { 49 | (char*) "B Voltage", 50 | (char*) "Speed", 51 | (char*) "RPM", 52 | (char*) "Temp 1", 53 | (char*) "Temp 2", 54 | (char*) "Temp 3", 55 | (char*) "Status 1", 56 | (char*) "PVC Stat", 57 | (char*) "Torque", 58 | (char*) "Batt Stat", 59 | (char*) "HUDL Stat", 60 | (char*) "PVC Stat", 61 | }; 62 | lcd.setDefaultSections(titles); 63 | 64 | // Set the default 65 | lcd.displaySectionHeaders(); 66 | lcd.setTextForSection(0, "3.2 v"); 67 | lcd.setTextForSection(1, "25 MPH"); 68 | lcd.setTextForSection(2, "3000"); 69 | lcd.setTextForSection(3, "40 C"); 70 | lcd.setTextForSection(4, "44 C"); 71 | lcd.setTextForSection(5, "43 C"); 72 | lcd.setTextForSection(6, "ON"); 73 | lcd.setTextForSection(7, "Ready"); 74 | lcd.setTextForSection(8, "100 NM"); 75 | lcd.setTextForSection(9, "Ready"); 76 | lcd.setTextForSection(10, "Ready"); 77 | lcd.setTextForSection(11, "Ready"); 78 | 79 | uint8_t number = 0; 80 | 81 | while (true) { 82 | char buffer[128] = {}; 83 | snprintf(buffer, (8), "%d", (number)); 84 | lcd.setTextForSection(1, buffer); 85 | 86 | number++; 87 | time::wait(500); 88 | } 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /src/core/platform/f4xx/stm32f446xx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | namespace core::platform { 10 | 11 | void stm32f4xx_init() { 12 | HAL_Init(); 13 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 14 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 15 | RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; 16 | 17 | /** Configure the main internal regulator output voltage 18 | */ 19 | __HAL_RCC_PWR_CLK_ENABLE(); 20 | __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); 21 | 22 | /** Initializes the RCC Oscillators according to the specified parameters 23 | * in the RCC_OscInitTypeDef structure. 24 | */ 25 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; 26 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; 27 | RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 28 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 29 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 30 | RCC_OscInitStruct.PLL.PLLM = 8; 31 | RCC_OscInitStruct.PLL.PLLN = 50; 32 | RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 33 | RCC_OscInitStruct.PLL.PLLQ = 2; 34 | RCC_OscInitStruct.PLL.PLLR = 2; 35 | HAL_RCC_OscConfig(&RCC_OscInitStruct); 36 | // if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 37 | // { 38 | // Error_Handler(); 39 | // } 40 | 41 | /** Initializes the CPU, AHB and APB buses clocks 42 | */ 43 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; 44 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // SYSCLK at 50 MHz (HSI CLK) 45 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 46 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; 47 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 48 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { 49 | Error_Handler(); 50 | } 51 | 52 | // ADC is currently configured to run based on AHB clock. 53 | // Enable the PLL Clock below and update 'halADC.Init.ClockPrescaler' to run ADC using faster PLL clock 54 | /* 55 | PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC1; 56 | PeriphClkInit.Adc1ClockSelection = RCC_ADC1PLLCLK_DIV1; 57 | 58 | HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); 59 | */ 60 | 61 | SysTick_Handler(); 62 | } 63 | 64 | void Error_Handler(void) { 65 | /* USER CODE BEGIN Error_Handler_Debug */ 66 | /* User can add his own implementation to report the HAL error return state */ 67 | __disable_irq(); 68 | /* USER CODE END Error_Handler_Debug */ 69 | } 70 | 71 | } // namespace core::platform 72 | -------------------------------------------------------------------------------- /libs/HALf4/include/HALf4/system_stm32f4xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f4xx.h 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2017 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | 19 | /** @addtogroup CMSIS 20 | * @{ 21 | */ 22 | 23 | /** @addtogroup stm32f4xx_system 24 | * @{ 25 | */ 26 | 27 | /** 28 | * @brief Define to prevent recursive inclusion 29 | */ 30 | #ifndef __SYSTEM_STM32F4XX_H 31 | #define __SYSTEM_STM32F4XX_H 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /** @addtogroup STM32F4xx_System_Includes 38 | * @{ 39 | */ 40 | 41 | /** 42 | * @} 43 | */ 44 | 45 | 46 | /** @addtogroup STM32F4xx_System_Exported_types 47 | * @{ 48 | */ 49 | /* This variable is updated in three ways: 50 | 1) by calling CMSIS function SystemCoreClockUpdate() 51 | 2) by calling HAL API function HAL_RCC_GetSysClockFreq() 52 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency 53 | Note: If you use this function to configure the system clock; then there 54 | is no need to call the 2 first functions listed above, since SystemCoreClock 55 | variable is updated automatically. 56 | */ 57 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 58 | 59 | extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ 60 | extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ 61 | 62 | /** 63 | * @} 64 | */ 65 | 66 | /** @addtogroup STM32F4xx_System_Exported_Constants 67 | * @{ 68 | */ 69 | 70 | /** 71 | * @} 72 | */ 73 | 74 | /** @addtogroup STM32F4xx_System_Exported_Macros 75 | * @{ 76 | */ 77 | 78 | /** 79 | * @} 80 | */ 81 | 82 | /** @addtogroup STM32F4xx_System_Exported_Functions 83 | * @{ 84 | */ 85 | 86 | extern void SystemInit(void); 87 | extern void SystemCoreClockUpdate(void); 88 | /** 89 | * @} 90 | */ 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif /*__SYSTEM_STM32F4XX_H */ 97 | 98 | /** 99 | * @} 100 | */ 101 | 102 | /** 103 | * @} 104 | */ 105 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 106 | -------------------------------------------------------------------------------- /libs/HALf4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # CMake file for exposing HAL as library. 3 | ############################################################################### 4 | cmake_minimum_required(VERSION 3.15) 5 | 6 | include(GNUInstallDirs) 7 | 8 | ############################################################################### 9 | # Project Setup 10 | ############################################################################### 11 | project(HALf4 12 | VERSION 0.0.1 13 | LANGUAGES C ASM 14 | ) 15 | 16 | add_library(${PROJECT_NAME} STATIC) 17 | 18 | # Glob together all C source files 19 | file(GLOB HALf4_C_SRC_FILES src/*.c) 20 | 21 | if(TARGET_DEV STREQUAL "STM32F446xx") 22 | set(STARTUP_ASSEMBLY src/startup_stm32f446xx.s) 23 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -STM32F446RETX_FLASH.ld") 24 | endif() 25 | 26 | # Handle assembly file 27 | set_source_files_properties( 28 | ${STARTUP_ASSEMBLY} 29 | PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp" 30 | ) 31 | 32 | # Add C and Assembly source files 33 | target_sources(${PROJECT_NAME} PRIVATE 34 | ${HALf4_C_SRC_FILES} 35 | ${STARTUP_ASSEMBLY} 36 | ) 37 | 38 | # Add headers privately. 39 | # NOTE: This is a flat inclusion of the headers as that is how the STM HAL 40 | # code expects the headers to be 41 | target_include_directories(${PROJECT_NAME} PRIVATE include/HALf4/) 42 | 43 | ############################################################################### 44 | # Compiler settings 45 | ############################################################################### 46 | # Add flags for specific version of hardware 47 | set(HALf4_HARDWARE_FLAGS "-mthumb -mcpu=cortex-m4") 48 | 49 | add_compile_definitions(USE_HAL_DRIVER) 50 | 51 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${HALf4_HARDWARE_FLAGS}") 52 | 53 | ############################################################################### 54 | # Expose library 55 | ############################################################################### 56 | target_include_directories(${PROJECT_NAME} 57 | PUBLIC $ 58 | $ 59 | ) 60 | 61 | target_compile_definitions(${PROJECT_NAME} PRIVATE -D_EXPORT) 62 | 63 | set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d") 64 | 65 | install(TARGETS ${PROJECT_NAME} 66 | EXPORT ${PROJECT_NAME}-config 67 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 68 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 69 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 70 | ) 71 | 72 | install( 73 | EXPORT ${PROJECT_NAME}-config 74 | NAMESPACE ${PROJECT_NAME}:: 75 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} 76 | ) 77 | 78 | install( 79 | DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ 80 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} 81 | ) 82 | -------------------------------------------------------------------------------- /include/core/io/platform/f3xx/ADCf3xx.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _EVT_ADCf3xx_ 2 | #define _EVT_ADCf3xx_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace core::io { 10 | 11 | enum class ADCPeriph { 12 | ONE 13 | }; 14 | 15 | class ADCf3xx : public ADC { 16 | public: 17 | /** 18 | * Setup the given pin for ADC usage 19 | * 20 | * @param[in] pin The pin to setup for ADC 21 | */ 22 | ADCf3xx(Pin pin, ADCPeriph adcPeriph); 23 | 24 | float read(); 25 | 26 | uint32_t readRaw(); 27 | 28 | float readPercentage(); 29 | 30 | private: 31 | // Max number of channels supported by the ADC 32 | static constexpr uint8_t MAX_CHANNELS = 15; 33 | // Positive reference voltage of the ADC. Needs to be updated based on the hardware configuration 34 | static constexpr float VREF_POS = 3.3; 35 | // Max value for a 12 bit ADC reading (2^12 - 1) 36 | static constexpr uint32_t MAX_RAW = 4095; 37 | /// This is static since the STM32F3xx only has a single ADC which 38 | /// supports multiple channels. The ADC will be initialized once then 39 | /// each channel will be added on. 40 | static ADC_HandleTypeDef halADC; 41 | /// Static list of all channels supported by the ADC 42 | static Pin channels[MAX_CHANNELS]; 43 | /// Buffer for DMA where each spot represents the value read in from a 44 | /// channel 45 | static uint16_t buffer[MAX_CHANNELS]; 46 | static DMA_HandleTypeDef halDMA; 47 | 48 | /** 49 | * Bit packed struct to contain the channel along with the ADC peripherals the channel supports 50 | * 51 | * adc1: 1 bit. Support for ADC1 peripheral. 1 for supported, 0 for not supported. 52 | * channel: 5 bits. The STM32 ADC channel value with said supported ADC peripherals 53 | */ 54 | struct Channel_Support { 55 | uint8_t adc1 : 1; 56 | uint8_t channel : 5; 57 | }; 58 | 59 | /** 60 | * Initialize the HAL ADC handler. This should only have to be run once 61 | */ 62 | void initADC(uint8_t num_channels); 63 | 64 | /** 65 | * Initialize the HAL DMA for the ADC, should only have to be run once 66 | */ 67 | void initDMA(); 68 | 69 | /** 70 | * Adds an ADC channel to the HAL ADC device. 71 | * 72 | * @param rank The "rank" which represents the order in which the channel 73 | * was added to the ADC starting at 1 74 | */ 75 | void addChannel(uint8_t rank); 76 | 77 | /** 78 | * Check if the channel that is being initialized supports the ADC peripheral that it is being initialized on. 79 | * 80 | * @param periph the ADC peripheral being used 81 | * @param channelStruct the struct of the channel with supports to test 82 | * @return true if channel is supported by the ADC peripheral, false otherwise 83 | */ 84 | static bool checkSupport(ADCPeriph periph, Channel_Support channelStruct); 85 | }; 86 | 87 | } // namespace core::io 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /libs/HALf3/include/HALf3/tz_context.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file tz_context.h 3 | * @brief Context Management for Armv8-M TrustZone 4 | * @version V1.0.1 5 | * @date 10. January 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2017-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef TZ_CONTEXT_H 32 | #define TZ_CONTEXT_H 33 | 34 | #include 35 | 36 | #ifndef TZ_MODULEID_T 37 | #define TZ_MODULEID_T 38 | /// \details Data type that identifies secure software modules called by a process. 39 | typedef uint32_t TZ_ModuleId_t; 40 | #endif 41 | 42 | /// \details TZ Memory ID identifies an allocated memory slot. 43 | typedef uint32_t TZ_MemoryId_t; 44 | 45 | /// Initialize secure context memory system 46 | /// \return execution status (1: success, 0: error) 47 | uint32_t TZ_InitContextSystem_S (void); 48 | 49 | /// Allocate context memory for calling secure software modules in TrustZone 50 | /// \param[in] module identifies software modules called from non-secure mode 51 | /// \return value != 0 id TrustZone memory slot identifier 52 | /// \return value 0 no memory available or internal error 53 | TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); 54 | 55 | /// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S 56 | /// \param[in] id TrustZone memory slot identifier 57 | /// \return execution status (1: success, 0: error) 58 | uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); 59 | 60 | /// Load secure context (called on RTOS thread context switch) 61 | /// \param[in] id TrustZone memory slot identifier 62 | /// \return execution status (1: success, 0: error) 63 | uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); 64 | 65 | /// Store secure context (called on RTOS thread context switch) 66 | /// \param[in] id TrustZone memory slot identifier 67 | /// \return execution status (1: success, 0: error) 68 | uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); 69 | 70 | #endif // TZ_CONTEXT_H 71 | -------------------------------------------------------------------------------- /libs/HALf3/include/HALf3/system_stm32f3xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f3xx.h 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M4 Device System Source File for STM32F3xx devices. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2016 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /** @addtogroup CMSIS 21 | * @{ 22 | */ 23 | 24 | /** @addtogroup stm32f3xx_system 25 | * @{ 26 | */ 27 | 28 | /** 29 | * @brief Define to prevent recursive inclusion 30 | */ 31 | #ifndef __SYSTEM_STM32F3XX_H 32 | #define __SYSTEM_STM32F3XX_H 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** @addtogroup STM32F3xx_System_Includes 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @} 44 | */ 45 | 46 | 47 | /** @addtogroup STM32F3xx_System_Exported_types 48 | * @{ 49 | */ 50 | /* This variable is updated in three ways: 51 | 1) by calling CMSIS function SystemCoreClockUpdate() 52 | 3) by calling HAL API function HAL_RCC_GetHCLKFreq() 53 | 3) by calling HAL API function HAL_RCC_ClockConfig() 54 | Note: If you use this function to configure the system clock; then there 55 | is no need to call the 2 first functions listed above, since SystemCoreClock 56 | variable is updated automatically. 57 | */ 58 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 59 | extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ 60 | extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ 61 | 62 | 63 | /** 64 | * @} 65 | */ 66 | 67 | /** @addtogroup STM32F3xx_System_Exported_Constants 68 | * @{ 69 | */ 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** @addtogroup STM32F3xx_System_Exported_Macros 76 | * @{ 77 | */ 78 | 79 | /** 80 | * @} 81 | */ 82 | 83 | /** @addtogroup STM32F3xx_System_Exported_Functions 84 | * @{ 85 | */ 86 | 87 | extern void SystemInit(void); 88 | extern void SystemCoreClockUpdate(void); 89 | /** 90 | * @} 91 | */ 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif /*__SYSTEM_STM32F3XX_H */ 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** 104 | * @} 105 | */ 106 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 107 | --------------------------------------------------------------------------------