From f044aedfbd76fca6101b0be30bbf40a47b03fbea Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 25 Nov 2022 22:16:12 +1000 Subject: [PATCH] boards: Tock: Initial commit of Tock support Signed-off-by: Alistair Francis --- .gitmodules | 3 + README.md | 3 + cmake/tock.cmake | 29 +++ doc/Tock.md | 4 + src/CMakeLists.txt | 11 + src/apps/ping-pong/CMakeLists.txt | 8 +- src/apps/ping-pong/Tock/main.c | 362 ++++++++++++++++++++++++++++++ src/boards/Tock/CMakeLists.txt | 48 ++++ src/boards/Tock/board-config.h | 35 +++ src/boards/Tock/board.c | 172 ++++++++++++++ src/boards/Tock/delay-board.c | 17 ++ src/boards/Tock/gpio-board.c | 132 +++++++++++ src/boards/Tock/libtock-c | 1 + src/boards/Tock/rtc-board.c | 204 +++++++++++++++++ src/boards/Tock/spi-board.c | 47 ++++ src/boards/Tock/sx126x-board.c | 278 +++++++++++++++++++++++ src/boards/Tock/uart-board.c | 63 ++++++ 17 files changed, 1416 insertions(+), 1 deletion(-) create mode 100644 cmake/tock.cmake create mode 100644 doc/Tock.md create mode 100644 src/apps/ping-pong/Tock/main.c create mode 100644 src/boards/Tock/CMakeLists.txt create mode 100644 src/boards/Tock/board-config.h create mode 100644 src/boards/Tock/board.c create mode 100644 src/boards/Tock/delay-board.c create mode 100644 src/boards/Tock/gpio-board.c create mode 160000 src/boards/Tock/libtock-c create mode 100644 src/boards/Tock/rtc-board.c create mode 100644 src/boards/Tock/spi-board.c create mode 100644 src/boards/Tock/sx126x-board.c create mode 100644 src/boards/Tock/uart-board.c diff --git a/.gitmodules b/.gitmodules index 0f8912b99..230e3056d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "src/peripherals/atecc608a-tnglora-se/cryptoauthlib"] path = src/peripherals/atecc608a-tnglora-se/cryptoauthlib url = https://github.com/MicrochipTech/cryptoauthlib +[submodule "src/boards/Tock/libtock-c"] + path = src/boards/Tock/libtock-c + url = https://github.com/tock/libtock-c.git diff --git a/README.md b/README.md index 8c8967352..e07b7f0dd 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,9 @@ The [Porting Guide](https://stackforce.github.io/LoRaMac-doc/LoRaMac-doc-v4.7.0/ * SAMR34 * [SAMR34 platform documentation](doc/SAMR34-platform.md) +* Tock + * [Tock](doc/Tock.md) + ## Getting Started ### Prerequisites diff --git a/cmake/tock.cmake b/cmake/tock.cmake new file mode 100644 index 000000000..c5b31573d --- /dev/null +++ b/cmake/tock.cmake @@ -0,0 +1,29 @@ +## License: Revised BSD License, see LICENSE.TXT file included in the project +## Authors: Alistair Francis +## +## Tock target specific CMake file +## + +if(NOT DEFINED LINKER_SCRIPT) +message(FATAL_ERROR "No linker script defined") +endif(NOT DEFINED LINKER_SCRIPT) +message("Linker script: ${LINKER_SCRIPT}") + + +#--------------------------------------------------------------------------------------- +# Set compiler/linker flags +#--------------------------------------------------------------------------------------- + +set(STACK_SIZE 2048) +set(APP_HEAP_SIZE 1024) +set(KERNEL_HEAP_SIZE 1024) + +# Object build options +set(OBJECT_GEN_FLAGS "-mthumb -g2 -fno-builtin -mcpu=cortex-m4 -Wall -Wextra -pedantic -Wno-unused-parameter -ffunction-sections -fdata-sections -fomit-frame-pointer -mabi=aapcs -fno-unroll-loops -ffast-math -ftree-vectorize -frecord-gcc-switches -gdwarf-2 -Os -fdata-sections -ffunction-sections -fstack-usage -Wl,--emit-relocs -fPIC -mthumb -mfloat-abi=soft -msingle-pic-base -mpic-register=r9 -mno-pic-data-is-text-relative -D__TOCK__ -DSVCALL_AS_NORMAL_FUNCTION -DSOFTDEVICE_s130") + +set(CMAKE_C_FLAGS "${OBJECT_GEN_FLAGS} -std=gnu99 " CACHE INTERNAL "C Compiler options") +set(CMAKE_CXX_FLAGS "${OBJECT_GEN_FLAGS} -std=c++11 " CACHE INTERNAL "C++ Compiler options") +set(CMAKE_ASM_FLAGS "${OBJECT_GEN_FLAGS} -x assembler-with-cpp " CACHE INTERNAL "ASM Compiler options") + +# Linker flags +set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections --specs=nano.specs --specs=nosys.specs -mthumb -g2 -mcpu=cortex-m4 -mabi=aapcs -T${LINKER_SCRIPT} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Xlinker --defsym=STACK_SIZE=${STACK_SIZE} -Xlinker --defsym=APP_HEAP_SIZE=${APP_HEAP_SIZE} -Xlinker --defsym=KERNEL_HEAP_SIZE=${KERNEL_HEAP_SIZE} -nostdlib -Wl,--start-group" CACHE INTERNAL "Linker options") diff --git a/doc/Tock.md b/doc/Tock.md new file mode 100644 index 000000000..e1b8b3587 --- /dev/null +++ b/doc/Tock.md @@ -0,0 +1,4 @@ +# TockNAMote72 platform support documents + +This is support for the [Tock](https://github.com/tock/tock) operating system, +allowing the library to run as a userspace application on Tock boards. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 248c2e218..8bde29cb6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -183,6 +183,17 @@ elseif(BOARD STREQUAL B-L072Z-LRWAN1) # Configure radio set(RADIO sx1276 CACHE INTERNAL "Radio sx1276 selected") + +elseif(BOARD STREQUAL Tock) + # Configure toolchain for Tock + set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/boards/Tock/libtock-c/userland_generic.ld) + include(tock) + + # Build platform specific board implementation + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/boards/Tock) + + # Configure radio + set(RADIO sx126x CACHE INTERNAL "Radio sx126x selected") endif() #--------------------------------------------------------------------------------------- diff --git a/src/apps/ping-pong/CMakeLists.txt b/src/apps/ping-pong/CMakeLists.txt index 1c42792cc..d6a2b2264 100644 --- a/src/apps/ping-pong/CMakeLists.txt +++ b/src/apps/ping-pong/CMakeLists.txt @@ -83,7 +83,13 @@ target_include_directories(${PROJECT_NAME} PUBLIC set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11) -target_link_libraries(${PROJECT_NAME} m) +# TODO: Remove this +target_link_libraries(${PROJECT_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/../../boards/Tock/libtock-c/newlib/cortex-m/v7-m/libc.a + ${CMAKE_CURRENT_SOURCE_DIR}/../../boards/Tock/libtock-c/newlib/cortex-m/v7-m/libm.a + ${CMAKE_CURRENT_SOURCE_DIR}/../../boards/Tock/libtock-c/libtock/build/cortex-m4/libtock.a +) + #--------------------------------------------------------------------------------------- # Debugging and Binutils diff --git a/src/apps/ping-pong/Tock/main.c b/src/apps/ping-pong/Tock/main.c new file mode 100644 index 000000000..2a1d60a2c --- /dev/null +++ b/src/apps/ping-pong/Tock/main.c @@ -0,0 +1,362 @@ +/*! + * \file main.c + * + * \brief Ping-Pong implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include +#include +#include "board.h" +#include "gpio.h" +#include "delay.h" +#include "timer.h" +#include "radio.h" + +#include "libtock/led.h" + +#if defined( REGION_AS923 ) + +#define RF_FREQUENCY 923000000 // Hz + +#elif defined( REGION_AU915 ) + +#define RF_FREQUENCY 915000000 // Hz + +#elif defined( REGION_CN470 ) + +#define RF_FREQUENCY 470000000 // Hz + +#elif defined( REGION_CN779 ) + +#define RF_FREQUENCY 779000000 // Hz + +#elif defined( REGION_EU433 ) + +#define RF_FREQUENCY 433000000 // Hz + +#elif defined( REGION_EU868 ) + +#define RF_FREQUENCY 868000000 // Hz + +#elif defined( REGION_KR920 ) + +#define RF_FREQUENCY 920000000 // Hz + +#elif defined( REGION_IN865 ) + +#define RF_FREQUENCY 865000000 // Hz + +#elif defined( REGION_US915 ) + +#define RF_FREQUENCY 915000000 // Hz + +#elif defined( REGION_RU864 ) + +#define RF_FREQUENCY 864000000 // Hz + +#else + #error "Please define a frequency band in the compiler options." +#endif + +#define TX_OUTPUT_POWER 14 // dBm + +#if defined( USE_MODEM_LORA ) + +#define LORA_BANDWIDTH 0 // [0: 125 kHz, + // 1: 250 kHz, + // 2: 500 kHz, + // 3: Reserved] +#define LORA_SPREADING_FACTOR 7 // [SF7..SF12] +#define LORA_CODINGRATE 1 // [1: 4/5, + // 2: 4/6, + // 3: 4/7, + // 4: 4/8] +#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx +#define LORA_SYMBOL_TIMEOUT 5 // Symbols +#define LORA_FIX_LENGTH_PAYLOAD_ON false +#define LORA_IQ_INVERSION_ON false + +#elif defined( USE_MODEM_FSK ) + +#define FSK_FDEV 25000 // Hz +#define FSK_DATARATE 50000 // bps +#define FSK_BANDWIDTH 50000 // Hz +#define FSK_AFC_BANDWIDTH 83333 // Hz +#define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx +#define FSK_FIX_LENGTH_PAYLOAD_ON false + +#else + #error "Please define a modem in the compiler options." +#endif + +typedef enum +{ + LOWPOWER, + RX, + RX_TIMEOUT, + RX_ERROR, + TX, + TX_TIMEOUT, +}States_t; + +#define RX_TIMEOUT_VALUE 1000 +#define BUFFER_SIZE 64 // Define the payload size here + +const uint8_t PingMsg[] = "PING"; +const uint8_t PongMsg[] = "PONG"; + +uint16_t BufferSize = BUFFER_SIZE; +uint8_t Buffer[BUFFER_SIZE]; + +States_t State = LOWPOWER; + +int8_t RssiValue = 0; +int8_t SnrValue = 0; + +/*! + * Radio events function pointer + */ +static RadioEvents_t RadioEvents; + +/*! + * \brief Function to be executed on Radio Tx Done event + */ +void OnTxDone( void ); + +/*! + * \brief Function to be executed on Radio Rx Done event + */ +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); + +/*! + * \brief Function executed on Radio Tx Timeout event + */ +void OnTxTimeout( void ); + +/*! + * \brief Function executed on Radio Rx Timeout event + */ +void OnRxTimeout( void ); + +/*! + * \brief Function executed on Radio Rx Error event + */ +void OnRxError( void ); + +/** + * Main application entry point. + */ +int main( void ) +{ + bool isMaster = true; + uint8_t i; + + printf("Starting the Tock Ping-Pong Application\r\n"); + + // Target board initialization + BoardInitMcu( ); + BoardInitPeriph( ); + + // Radio initialization + RadioEvents.TxDone = OnTxDone; + RadioEvents.RxDone = OnRxDone; + RadioEvents.TxTimeout = OnTxTimeout; + RadioEvents.RxTimeout = OnRxTimeout; + RadioEvents.RxError = OnRxError; + + Radio.Init( &RadioEvents ); + + Radio.SetChannel( RF_FREQUENCY ); + +#if defined( USE_MODEM_LORA ) + + Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, + LORA_SPREADING_FACTOR, LORA_CODINGRATE, + LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, + true, 0, 0, LORA_IQ_INVERSION_ON, 3000 ); + + Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, + LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, + LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); + + Radio.SetMaxPayloadLength( MODEM_LORA, BUFFER_SIZE ); + +#elif defined( USE_MODEM_FSK ) + + Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, + FSK_DATARATE, 0, + FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, + true, 0, 0, 0, 3000 ); + + Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, + 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0,false, true ); + + Radio.SetMaxPayloadLength( MODEM_FSK, BUFFER_SIZE ); + +#else + #error "Please define a frequency band in the compiler options." +#endif + + Radio.Rx( RX_TIMEOUT_VALUE ); + + printf("Running the Tock Ping-Pong Application\r\n"); + + while( 1 ) + { + // Tick the RTC to execute callback in context of the main loop (in stead of the IRQ) + TimerProcess( ); + + switch( State ) + { + case RX: + if( isMaster == true ) + { + if( BufferSize > 0 ) + { + if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 ) + { + // Indicates on a LED that the received frame is a PONG + led_toggle(0); + + // Send the next PING frame + Buffer[0] = 'P'; + Buffer[1] = 'I'; + Buffer[2] = 'N'; + Buffer[3] = 'G'; + // We fill the buffer with numbers for the payload + for( i = 4; i < BufferSize; i++ ) + { + Buffer[i] = i - 4; + } + DelayMs( 1 ); + Radio.Send( Buffer, BufferSize ); + } + else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) + { // A master already exists then become a slave + isMaster = false; + Radio.Rx( RX_TIMEOUT_VALUE ); + } + else // valid reception but neither a PING or a PONG message + { // Set device as master ans start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } + } + } + else + { + if( BufferSize > 0 ) + { + if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) + { + // Indicates on a LED that the received frame is a PING + led_toggle(0); + + // Send the reply to the PONG string + Buffer[0] = 'P'; + Buffer[1] = 'O'; + Buffer[2] = 'N'; + Buffer[3] = 'G'; + // We fill the buffer with numbers for the payload + for( i = 4; i < BufferSize; i++ ) + { + Buffer[i] = i - 4; + } + DelayMs( 1 ); + Radio.Send( Buffer, BufferSize ); + } + else // valid reception but not a PING as expected + { // Set device as master and start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } + } + } + State = LOWPOWER; + break; + case TX: + // Indicates on a LED that we have sent a PING [Master] + // Indicates on a LED that we have sent a PONG [Slave] + Radio.Rx( RX_TIMEOUT_VALUE ); + State = LOWPOWER; + break; + case RX_TIMEOUT: + case RX_ERROR: + if( isMaster == true ) + { + // Send the next PING frame + Buffer[0] = 'P'; + Buffer[1] = 'I'; + Buffer[2] = 'N'; + Buffer[3] = 'G'; + for( i = 4; i < BufferSize; i++ ) + { + Buffer[i] = i - 4; + } + DelayMs( 1 ); + Radio.Send( Buffer, BufferSize ); + } + else + { + Radio.Rx( RX_TIMEOUT_VALUE ); + } + State = LOWPOWER; + break; + case TX_TIMEOUT: + Radio.Rx( RX_TIMEOUT_VALUE ); + State = LOWPOWER; + break; + case LOWPOWER: + default: + // Set low power + break; + } + + BoardLowPowerHandler( ); + // Process Radio IRQ + if( Radio.IrqProcess != NULL ) + { + Radio.IrqProcess( ); + } + } +} + +void OnTxDone( void ) +{ + Radio.Sleep( ); + State = TX; +} + +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) +{ + Radio.Sleep( ); + BufferSize = size; + memcpy( Buffer, payload, BufferSize ); + RssiValue = rssi; + SnrValue = snr; + State = RX; +} + +void OnTxTimeout( void ) +{ + Radio.Sleep( ); + State = TX_TIMEOUT; +} + +void OnRxTimeout( void ) +{ + Radio.Sleep( ); + State = RX_TIMEOUT; +} + +void OnRxError( void ) +{ + Radio.Sleep( ); + State = RX_ERROR; +} diff --git a/src/boards/Tock/CMakeLists.txt b/src/boards/Tock/CMakeLists.txt new file mode 100644 index 000000000..82b0aa81c --- /dev/null +++ b/src/boards/Tock/CMakeLists.txt @@ -0,0 +1,48 @@ +## License: Revised BSD License, see LICENSE.TXT file included in the project +## Authors: Alistair Francis +## + +project(Tock) +cmake_minimum_required(VERSION 3.6) +enable_language(ASM) + +#--------------------------------------------------------------------------------------- +# Target +#--------------------------------------------------------------------------------------- + +list(APPEND ${PROJECT_NAME}_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/board.c" + "${CMAKE_CURRENT_SOURCE_DIR}/delay-board.c" + "${CMAKE_CURRENT_SOURCE_DIR}/gpio-board.c" + "${CMAKE_CURRENT_SOURCE_DIR}/rtc-board.c" + "${CMAKE_CURRENT_SOURCE_DIR}/spi-board.c" + "${CMAKE_CURRENT_SOURCE_DIR}/sx126x-board.c" + "${CMAKE_CURRENT_SOURCE_DIR}/uart-board.c" +) + +add_library(${PROJECT_NAME} OBJECT EXCLUDE_FROM_ALL ${${PROJECT_NAME}_SOURCES}) + +target_compile_definitions(${PROJECT_NAME} PUBLIC) + +# Add define if debbuger support is enabled +target_compile_definitions(${PROJECT_NAME} PUBLIC $<$:USE_DEBUGGER>) + +# Add define if radio debug pins support is enabled +target_compile_definitions(${PROJECT_NAME} PUBLIC $<$:USE_RADIO_DEBUG>) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libtock-c + $ + $ + $ + $ +) + +set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11) + +target_link_libraries(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/boards/Tock/libtock-c/libtock/build/cortex-m4/libtock.a + ${CMAKE_CURRENT_SOURCE_DIR}/boards/Tock/libtock-c/newlib/cortex-m/v7-m/libc.a + ${CMAKE_CURRENT_SOURCE_DIR}/boards/Tock/libtock-c/newlib/cortex-m/v7-m/libm.a +) diff --git a/src/boards/Tock/board-config.h b/src/boards/Tock/board-config.h new file mode 100644 index 000000000..8c6a9974f --- /dev/null +++ b/src/boards/Tock/board-config.h @@ -0,0 +1,35 @@ +/*! + * \file board-config.h + * + * \brief Board configuration + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + * + */ +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RADIO_BUSY 1 +#define RADIO_DIO_1 2 +#define RADIO_DIO_3 3 +#define RADIO_RESET 4 +#define RADIO_NSS 0 + +/*! + * Defines the time required for the TCXO to wakeup [ms]. + */ +#define BOARD_TCXO_WAKEUP_TIME 1 + + +#ifdef __cplusplus +} +#endif + +#endif // __BOARD_CONFIG_H__ diff --git a/src/boards/Tock/board.c b/src/boards/Tock/board.c new file mode 100644 index 000000000..ecf4b8225 --- /dev/null +++ b/src/boards/Tock/board.c @@ -0,0 +1,172 @@ +/*! + * \file board.c + * + * \brief Target board general functions implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include "utilities.h" +#include "delay.h" +#include "gpio.h" +#include "adc.h" +#include "spi.h" +#include "i2c.h" +#include "uart.h" +#include "timer.h" +#include "gps.h" +#include "mpl3115.h" +#include "mag3110.h" +#include "mma8451.h" +#include "sx9500.h" +#include "board-config.h" +#include "lpm-board.h" +#include "sx126x-board.h" +#include "board.h" + +#include "libtock/rng.h" +#include "libtock/console.h" +#include +#include + +void BoardCriticalSectionBegin( uint32_t *mask ) +{ +} + +void BoardCriticalSectionEnd( uint32_t *mask ) +{ +} + +void BoardInitPeriph( void ) +{ +} + +void BoardInitMcu( void ) +{ + SX126xIoInit( ); + SX126xIoDbgInit( ); + SX126xIoTcxoInit( ); +} + +void BoardResetMcu( void ) +{ +} + +void BoardDeInitMcu( void ) +{ +} + +uint32_t BoardGetRandomSeed( void ) +{ + uint32_t procid; + int num_bytes; + + int r = rng_sync((uint8_t *) &procid, 4, 4, &num_bytes); + + if (r != RETURNCODE_SUCCESS || num_bytes != 4) { + printf("RNG failure\n"); + exit(1); + } + + return procid; +} + +void BoardGetUniqueId( uint8_t *id ) +{ + *id = 0xAB; +} + +uint16_t BoardBatteryMeasureVoltage( void ) +{ + return 0; +} + +uint32_t BoardGetBatteryVoltage( void ) +{ + return 0; +} + +uint8_t BoardGetBatteryLevel( void ) +{ + return 0; +} + +Version_t BoardGetVersion( void ) +{ + Version_t boardVersion = { 0 }; + + boardVersion.Fields.Major = 2; + boardVersion.Fields.Major = 1; + + return boardVersion; +} + +void SystemClockConfig( void ) +{ +} + +void SystemClockReConfig( void ) +{ +} + +void SysTick_Handler( void ) +{ +} + +uint8_t GetBoardPowerSource( void ) +{ + return USB_POWER; +} + +void LpmEnterStopMode( void ) +{ + yield(); +} + +void LpmExitStopMode( void ) +{ +} + +void LpmEnterSleepMode( void ) +{ + yield(); +} + +void BoardLowPowerHandler( void ) +{ + yield(); +} + +int _swiwrite(int fd, const void *buf, uint32_t count) +{ + putnstr((const char*)buf, count); + return count; +} + +#ifdef USE_FULL_ASSERT + +#include + +/* + * Function Name : assert_failed + * Description : Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * Input : - file: pointer to the source file name + * - line: assert_param error line source number + * Output : None + * Return : None + */ +void assert_failed( uint8_t* file, uint32_t line ) +{ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %lu\n", file, line) */ + + printf( "Wrong parameters value: file %s on line %lu\n", ( const char* )file, line ); + /* Infinite loop */ + while( 1 ) + { + yield(); + } +} +#endif diff --git a/src/boards/Tock/delay-board.c b/src/boards/Tock/delay-board.c new file mode 100644 index 000000000..f253d2241 --- /dev/null +++ b/src/boards/Tock/delay-board.c @@ -0,0 +1,17 @@ +/*! + * \file delay-board.c + * + * \brief Target board delay implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include "delay-board.h" + +#include "libtock/timer.h" + +void DelayMsMcu( uint32_t ms ) +{ + delay_ms( ms ); +} diff --git a/src/boards/Tock/gpio-board.c b/src/boards/Tock/gpio-board.c new file mode 100644 index 000000000..7b3948385 --- /dev/null +++ b/src/boards/Tock/gpio-board.c @@ -0,0 +1,132 @@ +/*! + * \file gpio-board.c + * + * \brief Target board GPIO driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include "utilities.h" +#include "board-config.h" +#include "rtc-board.h" +#include "gpio-board.h" +#if defined( BOARD_IOE_EXT ) +#include "gpio-ioe.h" +#endif + +#include "libtock/lora_phy.h" + +static Gpio_t *GpioIrq[16]; + +static void lora_phy_gpio_Callback (int gpioPin, + __attribute__ ((unused)) int arg2, + __attribute__ ((unused)) int arg3, + __attribute__ ((unused)) void* userdata) +{ + uint8_t callbackIndex = 1; + + if( gpioPin > 0 ) + { + while( gpioPin != 0x01 ) + { + gpioPin = gpioPin >> 1; + callbackIndex++; + } + } + + if( ( GpioIrq[callbackIndex] != NULL ) && ( GpioIrq[callbackIndex]->IrqHandler != NULL ) ) + { + GpioIrq[callbackIndex]->IrqHandler( GpioIrq[callbackIndex]->Context ); + } +} + +void GpioMcuInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, uint32_t value ) +{ + obj->pin = pin; + obj->pinIndex = pin; + + if (mode == PIN_OUTPUT) { + lora_phy_gpio_enable_output(pin); + } else { + if (type == PIN_NO_PULL) { + lora_phy_gpio_enable_input(pin, PullNone); + } else if (type == PIN_PULL_UP) { + lora_phy_gpio_enable_input(pin, PullUp); + } else if (type == PIN_PULL_DOWN) { + lora_phy_gpio_enable_input(pin, PullDown); + } + } +} + +void GpioMcuSetContext( Gpio_t *obj, void* context ) +{ + obj->Context = context; +} + +void GpioMcuSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ) +{ + if (obj->pinIndex == RADIO_NSS) { + // Skip the chips select as Tock handles this for us + return; + } + + obj->IrqHandler = irqHandler; + + GpioIrq[( obj->pin ) & 0x0F] = obj; + + lora_phy_gpio_interrupt_callback(lora_phy_gpio_Callback, NULL); + + // set GPIO as input and enable interrupts on it + lora_phy_gpio_enable_input(obj->pinIndex, PullDown); + lora_phy_gpio_enable_interrupt(obj->pinIndex, Change); + +} + +void GpioMcuRemoveInterrupt( Gpio_t *obj ) +{ + if (obj->pinIndex == RADIO_NSS) { + // Skip the chips select as Tock handles this for us + return; + } + + lora_phy_gpio_disable_interrupt(obj->pinIndex); +} + +void GpioMcuWrite( Gpio_t *obj, uint32_t value ) +{ + if (obj->pinIndex == RADIO_NSS) { + // Skip the chips select as Tock handles this for us + return; + } + + if (value) { + lora_phy_gpio_set(obj->pinIndex); + } else { + lora_phy_gpio_clear(obj->pinIndex); + } +} + +void GpioMcuToggle( Gpio_t *obj ) +{ + if (obj->pinIndex == RADIO_NSS) { + // Skip the chips select as Tock handles this for us + return; + } + + lora_phy_gpio_toggle(obj->pinIndex); +} + +uint32_t GpioMcuRead( Gpio_t *obj ) +{ + int value; + + if (obj->pinIndex == RADIO_NSS) { + // Skip the chips select as Tock handles this for us + return 0; + } + + lora_phy_gpio_read(obj->pinIndex, &value); + + return value; +} diff --git a/src/boards/Tock/libtock-c b/src/boards/Tock/libtock-c new file mode 160000 index 000000000..fdc6e1e45 --- /dev/null +++ b/src/boards/Tock/libtock-c @@ -0,0 +1 @@ +Subproject commit fdc6e1e45907bdabfb94b63c4be2de9e91d08340 diff --git a/src/boards/Tock/rtc-board.c b/src/boards/Tock/rtc-board.c new file mode 100644 index 000000000..eb9edfb35 --- /dev/null +++ b/src/boards/Tock/rtc-board.c @@ -0,0 +1,204 @@ +/*! + * \file rtc-board.c + * + * \brief Target board RTC timer and low power modes management + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include +#include +#include "utilities.h" +#include "delay.h" +#include "board.h" +#include "timer.h" +#include "systime.h" +#include "gpio.h" +#include "lpm-board.h" +#include "rtc-board.h" + +#include "libtock/timer.h" +#include "libtock/alarm.h" +#include "libtock/read_only_state.h" + +// MCU Wake Up Time +#define MIN_ALARM_DELAY 3 // in ticks + +// sub-second number of bits +#define N_PREDIV_S 10 + +// Synchronous prediv +#define PREDIV_S ( ( 1 << N_PREDIV_S ) - 1 ) + +// Asynchronous prediv +#define PREDIV_A ( 1 << ( 15 - N_PREDIV_S ) ) - 1 + +/*! + * RTC timer context + */ +typedef struct +{ + uint32_t Time; // Reference time +}RtcTimerContext_t; + +void* read_only_state_buffer = NULL; + +static tock_timer_t timer; +static uint32_t alarm_set_time = 0; + +static void timer_fired(__attribute__ ((unused)) int arg0, + __attribute__ ((unused)) int arg1, + __attribute__ ((unused)) int arg2, + __attribute__ ((unused)) void* ud) +{ + TimerIrqHandler(); +} + +/*! + * Keep the value of the RTC timer when the RTC alarm is set + * Set with the \ref RtcSetTimerContext function + * Value is kept as a Reference to calculate alarm + */ +static RtcTimerContext_t RtcTimerContext; + +void RtcInit( void ) +{ + read_only_state_buffer = malloc(READ_ONLY_STATEBUFFER_LEN); + + read_only_state_allocate_region(read_only_state_buffer, READ_ONLY_STATEBUFFER_LEN); +} + +uint32_t RtcSetTimerContext( void ) +{ + RtcTimerContext.Time = RtcGetTimerValue(); + + return RtcTimerContext.Time; +} + +uint32_t RtcGetTimerContext( void ) +{ + return RtcTimerContext.Time; +} + +/*! + * \brief returns the wake up time in ticks + * + * \retval wake up time in ticks + */ +uint32_t RtcGetMinimumTimeout( void ) +{ + uint32_t frequency; + alarm_internal_frequency(&frequency); + + return frequency; +} + +/*! + * \brief converts time in ms to time in ticks + * + * \param[IN] milliseconds Time in milliseconds + * \retval returns time in timer ticks + */ +uint32_t RtcMs2Tick( uint32_t milliseconds ) +{ + uint32_t frequency; + alarm_internal_frequency(&frequency); + + return (milliseconds / 1000) * frequency + (milliseconds % 1000) * (frequency / 1000); +} + +/*! + * \brief converts time in ticks to time in ms + * + * \param[IN] time in timer ticks + * \retval returns time in milliseconds + */ +uint32_t RtcTick2Ms( uint32_t tick ) +{ + uint32_t frequency; + alarm_internal_frequency(&frequency); + + return (tick / frequency) * 1000; +} + +/*! + * \brief a delay of delay ms by polling RTC + * + * \param[IN] delay in ms + */ +void RtcDelayMs( uint32_t delay ) +{ + delay_ms(delay); +} + +/*! + * \brief Sets the alarm + * + * \note The alarm is set at now (read in this function) + timeout + * + * \param timeout Duration of the Timer ticks + */ +void RtcSetAlarm( uint32_t timeout ) +{ + timer_in(timeout, timer_fired, NULL, &timer); + alarm_set_time = RtcGetTimerValue(); +} + +void RtcStopAlarm( void ) +{ + timer_cancel(&timer); + alarm_set_time = 0; +} + +void RtcStartAlarm( uint32_t timeout ) +{ + RtcSetAlarm(timeout); +} + +uint32_t RtcGetTimerValue( void ) +{ + if (read_only_state_buffer == NULL) { + uint32_t now; + alarm_internal_read(&now); + return now; + } else { + return read_only_state_get_ticks(read_only_state_buffer); + } +} + +uint32_t RtcGetTimerElapsedTime( void ) +{ + if (read_only_state_buffer == NULL) { + uint32_t now; + alarm_internal_read(&now); + return now - alarm_set_time; + } else { + return read_only_state_get_ticks(read_only_state_buffer) - alarm_set_time; + } +} + +uint32_t RtcGetCalendarTime( uint16_t *milliseconds ) +{ + return 0; +} + +void RtcBkupWrite( uint32_t data0, uint32_t data1 ) +{ +} + +void RtcBkupRead( uint32_t *data0, uint32_t *data1 ) +{ + *data0 = 0; + *data1 = 0; +} + +void RtcProcess( void ) +{ + yield_no_wait(); +} + +TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature ) +{ + return period; +} diff --git a/src/boards/Tock/spi-board.c b/src/boards/Tock/spi-board.c new file mode 100644 index 000000000..f696ae3cd --- /dev/null +++ b/src/boards/Tock/spi-board.c @@ -0,0 +1,47 @@ +/*! + * \file spi-board.c + * + * \brief Target board SPI driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include "utilities.h" +#include "board.h" +#include "gpio.h" +#include "spi-board.h" +#include "libtock/lora_phy.h" + +void SpiInit( Spi_t *obj, SpiId_t spiId, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss ) +{ +} + +void SpiDeInit( Spi_t *obj ) +{ +} + +void SpiFormat( Spi_t *obj, int8_t bits, int8_t cpol, int8_t cpha, int8_t slave ) +{ + lora_phy_set_polarity(cpol); + lora_phy_set_phase(cpha); +} + +void SpiFrequency( Spi_t *obj, uint32_t hz ) +{ + lora_phy_set_rate(hz); +} + +#define BUF_SIZE 1 + +char rbuf[BUF_SIZE]; +char wbuf[BUF_SIZE]; + +uint16_t SpiInOut( Spi_t *obj, uint16_t outData ) +{ + wbuf[0] = outData & 0xFF; + + lora_phy_read_write_sync(wbuf, rbuf, BUF_SIZE); + + return rbuf[0]; +} diff --git a/src/boards/Tock/sx126x-board.c b/src/boards/Tock/sx126x-board.c new file mode 100644 index 000000000..7748a8063 --- /dev/null +++ b/src/boards/Tock/sx126x-board.c @@ -0,0 +1,278 @@ +/*! + * \file sx1261mbxbas-board.c + * + * \brief Target board SX1261MBXBAS shield driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \author Alistair Francis + */ +#include +#include +#include +#include "utilities.h" +#include "board-config.h" +#include "board.h" +#include "delay.h" +#include "radio.h" +#include "sx126x-board.h" +#include "gpio-board.h" + +#include "libtock/gpio.h" +#include "libtock/lora_phy.h" + +/*! + * \brief Holds the internal operating mode of the radio + */ +static RadioOperatingModes_t OperatingMode; + +void SX126xIoInit( void ) +{ + GpioInit( &SX126x.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &SX126x.BUSY, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &SX126x.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +} + +void SX126xIoIrqInit( DioIrqHandler dioIrq ) +{ + GpioSetInterrupt( &SX126x.DIO1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, dioIrq ); +} + +void SX126xIoDeInit( void ) +{ + GpioInit( &SX126x.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &SX126x.BUSY, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &SX126x.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +} + +void SX126xIoDbgInit( void ) +{ +} + +void SX126xIoTcxoInit( void ) +{ +} + +uint32_t SX126xGetBoardTcxoWakeupTime( void ) +{ + return BOARD_TCXO_WAKEUP_TIME; +} + +void SX126xIoRfSwitchInit( void ) +{ + SX126xSetDio2AsRfSwitchCtrl( true ); +} + +RadioOperatingModes_t SX126xGetOperatingMode( void ) +{ + return OperatingMode; +} + +void SX126xSetOperatingMode( RadioOperatingModes_t mode ) +{ +} + +void SX126xReset( void ) +{ + DelayMs( 10 ); + GpioInit( &SX126x.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioMcuWrite(&SX126x.Reset, 0); + DelayMs( 20 ); + GpioMcuWrite(&SX126x.Reset, 1); + DelayMs( 10 ); +} + +void SX126xWaitOnBusy( void ) +{ + while( GpioRead( &SX126x.BUSY ) == 1 ); +} + +void SX126xWakeup( void ) +{ + char wbuf[2] = {RADIO_GET_STATUS, 0}; + char rbuf[2]; + + lora_phy_read_write_sync(wbuf, rbuf, 2); + + // Wait for chip to be ready. + SX126xWaitOnBusy( ); + + // Update operating mode context variable + SX126xSetOperatingMode( MODE_STDBY_RC ); +} + +void SX126xWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size ) +{ + char wbuf[size + 1]; + + SX126xCheckDeviceReady( ); + + bzero(wbuf, size + 1); + wbuf[0] = command; + + for( uint16_t i = 0; i < size; i++ ) + { + wbuf[1 + i] = buffer[i]; + } + + lora_phy_write_sync(wbuf, size + 1); + + if( command != RADIO_SET_SLEEP ) + { + SX126xWaitOnBusy( ); + } +} + +uint8_t SX126xReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size ) +{ + char wbuf[size + 2]; + char rbuf[size + 2]; + uint8_t status = 0; + + SX126xCheckDeviceReady( ); + + bzero(wbuf, size + 2); + wbuf[0] = command; + wbuf[1] = 0x00; // NOP + + lora_phy_read_write_sync(wbuf, rbuf, size + 2); + + status = rbuf[1]; + + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = rbuf[i + 2]; + } + + SX126xWaitOnBusy( ); + + return status; +} + +void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + char wbuf[size + 3]; + + SX126xCheckDeviceReady( ); + + bzero(wbuf, size + 3); + wbuf[0] = RADIO_WRITE_REGISTER; + wbuf[1] = ( address & 0xFF00 ) >> 8 ; + wbuf[2] = address & 0x00FF; + + for( uint16_t i = 0; i < size; i++ ) + { + wbuf[3 + i] = buffer[i]; + } + + lora_phy_write_sync(wbuf, size + 3); + + SX126xWaitOnBusy( ); +} + +void SX126xWriteRegister( uint16_t address, uint8_t value ) +{ + SX126xWriteRegisters( address, &value, 1 ); +} + +void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + char wbuf[size + 4]; + char rbuf[size + 4]; + + SX126xCheckDeviceReady( ); + + bzero(wbuf, size + 4); + wbuf[0] = RADIO_READ_REGISTER; + wbuf[1] = ( address & 0xFF00 ) >> 8 ; + wbuf[2] = address & 0x00FF; + wbuf[3] = 0x00; // NOP + + lora_phy_read_write_sync(wbuf, rbuf, size + 4); + + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = rbuf[i + 4]; + } + + SX126xWaitOnBusy( ); +} + +uint8_t SX126xReadRegister( uint16_t address ) +{ + uint8_t data; + SX126xReadRegisters( address, &data, 1 ); + return data; +} + +void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + char wbuf[size + 2]; + + SX126xCheckDeviceReady( ); + + bzero(wbuf, size + 2); + wbuf[0] = RADIO_WRITE_BUFFER; + wbuf[1] = offset; + + for( uint16_t i = 0; i < size; i++ ) + { + wbuf[2 + i] = buffer[i]; + } + + lora_phy_write_sync(wbuf, size + 2); + + + SX126xWaitOnBusy( ); +} + +void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + char wbuf[size + 3]; + char rbuf[size + 3]; + + SX126xCheckDeviceReady( ); + + bzero(wbuf, size + 3); + wbuf[0] = RADIO_READ_BUFFER; + wbuf[1] = offset; + wbuf[2] = 0x00; // NOP + + lora_phy_read_write_sync(wbuf, rbuf, size + 3); + + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = rbuf[i + 3]; + } + + SX126xWaitOnBusy( ); +} + +void SX126xSetRfTxPower( int8_t power ) +{ + SX126xSetTxParams( power, RADIO_RAMP_40_US ); +} + +uint8_t SX126xGetDeviceId( void ) +{ + return SX1262; +} + +void SX126xAntSwOn( void ) +{ +} + +void SX126xAntSwOff( void ) +{ +} + +bool SX126xCheckRfFrequency( uint32_t frequency ) +{ + // Implement check. Currently all frequencies are supported + return true; +} + +uint32_t SX126xGetDio1PinState( void ) +{ + return GpioRead( &SX126x.DIO1 ); +} diff --git a/src/boards/Tock/uart-board.c b/src/boards/Tock/uart-board.c new file mode 100644 index 000000000..e6490d74e --- /dev/null +++ b/src/boards/Tock/uart-board.c @@ -0,0 +1,63 @@ +/*! + * \file uart-board.c + * + * \brief Target board UART driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#include "utilities.h" +#include "board.h" +#include "uart-board.h" + +#include "libtock/console.h" + +void UartMcuInit( Uart_t *obj, UartId_t uartId, PinNames tx, PinNames rx ) +{ +} + +void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_t wordLength, StopBits_t stopBits, Parity_t parity, FlowCtrl_t flowCtrl ) +{ +} + +void UartMcuDeInit( Uart_t *obj ) +{ +} + +uint8_t UartMcuPutChar( Uart_t *obj, uint8_t data ) +{ + putstr(&data); +} + +uint8_t UartMcuGetChar( Uart_t *obj, uint8_t *data ) +{ + *data = getch(); + + return 0; +} + +uint8_t UartMcuPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size ) +{ + putnstr(buffer, size); +} + +uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes ) +{ + *nbReadBytes = getnstr(buffer, size); + + return 0; +}