diff --git a/platform/nrf52dk/Makefile.nrf52dk b/platform/nrf52dk/Makefile.nrf52dk new file mode 100644 index 000000000..8fa911cc4 --- /dev/null +++ b/platform/nrf52dk/Makefile.nrf52dk @@ -0,0 +1,34 @@ +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +### Include the board-specific makefile +PLATFORM_ROOT_DIR = $(CONTIKI)/platform/$(TARGET) + +CONTIKI_TARGET_DIRS += . dev config +CONTIKI_SOURCEFILES += contiki-main.c leds-arch.c nrf52dk-sensors.c button-sensor.c temperature-sensor.c + +ifeq ($(NRF52_USE_RTT),1) +### Use the existing debug I/O in cpu/arm/common +CONTIKI_TARGET_DIRS += rtt +CONTIKI_SOURCEFILES += rtt-printf.c segger-rtt.c segger-rtt-printf.c +else +CONTIKI_TARGET_DIRS += dbg-io +CONTIKI_SOURCEFILES += dbg.c +CONTIKI_CPU_DIRS += ../arm/common/dbg-io +CONTIKI_CPU_SOURCEFILES += dbg-printf.c dbg-putchar.c dbg-snprintf.c dbg-sprintf.c strformat.c +endif + +CLEAN += *.nrf52dk + +### Unless the example dictates otherwise, build with code size optimisations switched +### off +ifndef SMALL + SMALL = 0 +endif + +### Define the CPU directory and pull in the correct CPU makefile. +CONTIKI_CPU=$(CONTIKI)/cpu/nrf52832 +include $(CONTIKI_CPU)/Makefile.nrf52832 + +MODULES += core/net core/net/mac core/net/llsec diff --git a/platform/nrf52dk/README-BLE-6LoWPAN.md b/platform/nrf52dk/README-BLE-6LoWPAN.md new file mode 100644 index 000000000..e4c9ef5f6 --- /dev/null +++ b/platform/nrf52dk/README-BLE-6LoWPAN.md @@ -0,0 +1,100 @@ +This README contains information how to establish an IPv6 connecton between +Linux BLE router and an IPSP enabled BLE device. + +Prerequisites +============= +In general, any device capable of running Linux operating system, can be used +as a BLE router provided the following conditions are met: + +* Linux Kernel >3.18 is used +* bluez, libcap-ng0, radvd tools are present. + +If a built-in Bluetooth device is not available then Bluetooth 4.0 compatible +USB dongle can be used. + +The following procedures have been tested on Ubuntu 15.10. + +Establishing an IPv6 connection +=============================== +Use the following procedure to establish a connection between an nRF52 device +and Linux router: + +First enable 6LoWPAN module. This is neccessary only once per session: + + # Log in as a root user. + sudo su + + # Mount debugfs file system. + mount -t debugfs none /sys/kernel/debug + + # Load 6LoWPAN module. + modprobe bluetooth_6lowpan + + # Enable the bluetooth 6lowpan module. + echo 1 > /sys/kernel/debug/bluetooth/6lowpan_enable + + # Look for available HCI devices. + hciconfig + + # Reset HCI device - for example hci0 device. + hciconfig hci0 reset + + # Read 00:AA:BB:XX:YY:ZZ address of the nRF5x device. + hcitool lescan + +If you see device name and address in lescan output then you can connect to the +device: + + echo "connect 00:AA:BB:XX:YY:ZZ 1" > /sys/kernel/debug/bluetooth/6lowpan_control + +If above is successful then LED1 will stop blinking and LED2 will switch on. +You can then check the connection using the following commands: + + # Check if bt0 interface is present and up + ifconfig + + # Try to ping the device using its link-local address, for example, on bt0 interface. + ping6 -I bt0 fe80::2aa:bbff:fexx:yyzz + +If you'd like to learn more about the procedure please refer to +[Connecting devices to the router]. + +Distributing routable IPv6 prefix +================================= +In Linux, Router Advertisement Daemon (RADVD) can be used to distribute prefixes +in the network, hance configure routable IPv6 address. + +To configure RADVD create `/etc/radvd.conf` file and paste the following contents: + + interface bt0 + { + AdvSendAdvert on; + prefix 2001:db8::/64 + { + AdvOnLink off; + AdvAutonomous on; + AdvRouterAddr on; + }; + }; + +Next, start RADVD daemon: + + # Set IPv6 forwarding (must be present). + sudo echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + # Run radvd daemon. + sudo service radvd restart + +If successfull then all devices connected to the host will receive +a routable `2001:db8` prefix. + +This can be verified by sending echo request to the full address: + + ping6 -I bt0 2001:db8::2aa:bbff:fexx:yyzz + +where `aa:bbff:fexx:yyzz` is device Bluetooth address. + +If you'd like to learn more about the procedure please refer to +[Distributing a global IPv6 prefix]. + +* [Connecting devices to the router]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00089.html +* [Distributing a global IPv6 prefix]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00090.html \ No newline at end of file diff --git a/platform/nrf52dk/README.md b/platform/nrf52dk/README.md new file mode 100644 index 000000000..236892858 --- /dev/null +++ b/platform/nrf52dk/README.md @@ -0,0 +1,254 @@ +Contiki for nRF52 Development Kit +================================= +This guide's aim is to help you with using Contiki for +Nordic Semiconductor's nRF52 DK. + +The port depends on Nordic Semiconductor IoT SDK for nRF52. +The IoT SDK contains source code and libraries which are +required for successfull port compilation. It also contains +SoftDevice binary driver which is required for BLE operation. +See prerequisites section for details on how to set up the SDK. + +For more information about SoftDevice please refer to the SDK +docummentation [nRF52 Datasheet and SDK documentation]. + +This port supports DK versions PCA10040 and PCA10036. + +Port Features +============= +The following features have been implemented: +* Support for IPv6 over BLE using Contiki 6LoWPAN implementation +* Contiki system clock and rtimers (using 32kHz and 1MHz timers) +* UART driver +* Watchdog driver +* Hardware RNG +* Temperature sensor driver +* DK LED driver +* DK Buttons driver +* Real Time Transfer (RTT) I/O support + +Note that this port supports only IPv6 network stack. + +The port is organized as follows: +* nRF52832 CPU and BLE drivers are located in `cpu/nrf52832` folder +* nRF52 Development Kit drivers are located in `platform/nrf52dk` folder +* Platform examples are located in `examples/nrf52dk` folder + +Prerequisites and Setup +======================= +In order to compile for the nRF52 DK platform you'll need: + +* nRF5 IOT SDK + https://developer.nordicsemi.com + + Download nRF5 IOT SDK, extract it to a folder of your choice, + and point `NRF52_SDK_ROOT` environmental variable to it, e.g.,: + + ``` + wget https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip + unzip nrf5_iot_sdk_3288530.zip -d /path/to/sdk + export NRF52_SDK_ROOT=/path/to/sdk + ``` + +* An ARM compatible toolchain + The port has been tested with GNU Tools for ARM Embedded Processors + version 5.2.1. + + For Ubuntu you can use package version provided by your distribution: + ``` + sudo apt-get install gcc-arm-none-eabi + ``` + + Alternatively, install the toolchain from PPA to get the latest version + of the compiler: https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa + + For other systems please download and install toolchain available at + https://launchpad.net/gcc-arm-embedded + +* GNU make + +* Segger JLink Software for Linux + https://www.segger.com/jlink-software.html + + This package contains tools necessary for programming and debugging nRF52 DK. + + For Ubuntu you can download and install a .deb package. Alternatively download + tar.gz archive and extract it to a folder of your choice. In this case you + need to set `NRF52_JLINK_PATH` environmental variable to point to the + JLink tools location: + + ``` + export NRF52_JLINK_PATH=/path/to/jlink/tools + ``` + + To keep this variable set between sessions please add the above line to your + `rc.local` file. + + In order to access the DK as a regular Linux user create a `99-jlink.rules` + file in your udev rules folder (e.g., `/etc/udev/rules.d/`) and add the + following line to it: + + ``` + ATTRS{idProduct}=="1015", ATTRS{idVendor}=="1366", MODE="0666" + ``` + When installing from a deb package, the `99-jlink.rules` file is added + automatically to /etc/udev/rules.d folder. However, the syntax of the file + doesn't work on newer udev versions. To fix this problem edit this file and + replace ATTR keyword with ATTRS. + +To fully use the platform a BLE enabled router device is needed. Please refer +to `Preqrequisites` section in `README-BLE-6LoWPAN.md` for details. + +Getting Started +=============== +Once all tools are installed it is recommended to start by compiling +and flashing `examples/hello-word` application. This allows to verify +that toolchain setup is correct. + +To compile the example, go to `examples/hello-world` and execute: + + make TARGET=nrf52dk + +If you haven't used the device with Contiki before we advise to +erase the device and flash new SoftDevice: + + make TARGET=nrf52dk erase + make TARGET=nrf52dk softdevice.flash + +If the compilation is completed without errors flash the board: + + make TARGET=nrf52dk hello-world.flash + +The device will start BLE advertising as soon as initialized. By +default the device name is set to 'Contiki nRF52 DK'. To verify +that the device is advertising properly run: + + sudo hcitool lescan + +And observe if the device name appears in the output. Also, observe +if LED1 is blinking what indicates that device is waiting for a connection +from BLE master. + +If device is functioning as expected you can test IPv6 connection +to the device. Please refer to `README-BLE-6LoWPAN.md` on details how to do +this. + +Examples +======== +Examples specific for nRF52 DK can be found in `examples/nrf52dk` folder. Please +refer to README.md in respective examples for detailed description. + +The DK has also been tested with the `examples/hello-world` and `examples/webserver-ipv6` +generic examples. + +Compilation Options +=================== +The Contiki TARGET name for this port is `nrf52dk`, so in order to compile +an application you need to invoke GNU make as follows: + + make TARGET=nrf52dk + +In addition to this port supports the following variables which can be +set on the compilation command line: + +* `NRF52_SDK_ROOT=` + This variable allows to specify a path to the nRF52 SDK which should + be used for the build. + +* `NRF52_WITHOUT_SOFTDEVICE={0|1}` + Disables SoftDevice support if set to 1. By default, SoftDevice support + is used. Note that SoftDevice must be present (flashed) in the device + before you run an application that requires it's presence. + +* `NRF52_USE_RTT={0|1}` + Enables RealTime Terminal I/O. See VCOM and RTT for details. By default, + RTT is disabled and IO is done using Virtual COM port. + +* `NRF52_JLINK_SN=` + Allows to choose a particular DK by its serial number (printed on the + label). This is useful if you have more than one DK connected to your + PC and whish to flash a particular device. + +* `NRF52_DK_REVISION={pca10040|pca10036}` + Allows to specify DK revision. By default, pca10040 is used. + +Compilation Targets +=================== +Invoking make solely with the `TARGET` variable set will build all +applications in a given folder. A particular application can be built +by invoking make with its name as a compilation target: + + make TARGET=nrf52dk hello-world + +In order to flash the application binary to the device use `.flash` +as make target, e.g.: + + make TARGET=nrf52dk hello-world.flash + +In addition, the SoftDevice binary can be flashed to the DK by invoking: + + make TARGET=nrf52dk softdevice.flash + +To remove all build results invoke: + + make TARGET=nrf52dk clean + +The device memory can be erased using: + + make TARGET=nrf52dk erase + +Note, that once the device is erased, the SoftDevice must be programmed again. + +Virtual COM and Real Time Transfer +================================== +By default, the nRF52 DK uses a Virtual COM port to output logs. Once +the DK is plugged in a `/tty/ACM` or `/ttyUSB` device should appear in +your filesystem. A terminal emulator, such as picocom or minicom, can be +used to connect to the device. Default serial port speed is 38400 bps. + +To connect to serial port using picocom invoke: + + picocom -fh -b 38400 --imap lfcrlf /dev/ttyACM0 + +Note, that if you have not fixed file permissions for `/dev/ttyACM0` +according to section `Segger JLink Software for Linux` you'll need to use +root or sudo to open the port with `picocom`. + +In addition to Virtual COM the port supports SEGGER's Real Time Transfer +for low overhead I/O support. This allows for outputting debugging information +at much higher rate with significantly lower overhead than regular I/O. + +To compile an application with RTT rather that VCOM set `NRF52_USE_RTT` to 1 on +the compilation command line: + + make TARGET=nrf52dk NRF52_USE_RTT=1 hello-world + +You can then connect to the device terminal using `JLinkRTTClient`. Note that +a JLlink gdb or commander must be connected to the target for the RTT to work. + +More details regarding RTT can be found at https://www.segger.com/jlink-rtt.html + +Docummentation +============== +This port provides doxygen source code docummentation. To build the +docummentation please run: + + sudo apt-get install doxygen + cd \doc + make + +Support +======= +This port is officially supported by Nordic Semiconductor. Please send bug +reports or/and suggestions to . + +License +======= +All files in the port are under BSD license. nRF52 SDK and SoftDevice are +licensed on a separate terms. + +Resources +========= +* nRF52 Datasheet and SDK documentation (http://infocenter.nordicsemi.com) +* nRF52 SDK Downloads (https://developer.nordicsemi.com/) +* JLink Tools (https://www.segger.com/) \ No newline at end of file diff --git a/platform/nrf52dk/config/nrf_drv_config.h b/platform/nrf52dk/config/nrf_drv_config.h new file mode 100644 index 000000000..cfc3595b2 --- /dev/null +++ b/platform/nrf52dk/config/nrf_drv_config.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \defgroup nrf52dk-config nRF52 SDK configuration + * @{ + */ + +#ifndef NRF_DRV_CONFIG_H +#define NRF_DRV_CONFIG_H + +/* CLOCK */ +#define CLOCK_CONFIG_XTAL_FREQ NRF_CLOCK_XTALFREQ_Default +#define CLOCK_CONFIG_LF_SRC NRF_CLOCK_LF_SRC_Xtal +#define CLOCK_CONFIG_LF_RC_CAL_INTERVAL RC_2000MS_CALIBRATION_INTERVAL +#define CLOCK_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +/* GPIOTE */ +#define GPIOTE_ENABLED 1 + +#if (GPIOTE_ENABLED == 1) +#define GPIOTE_CONFIG_USE_SWI_EGU false +#define GPIOTE_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +/* TIMER */ +#define TIMER0_ENABLED 0 + +#if (TIMER0_ENABLED == 1) +#define TIMER0_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER0_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER0_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER0_INSTANCE_INDEX 0 +#endif + +#define TIMER1_ENABLED 1 + +#if (TIMER1_ENABLED == 1) +#define TIMER1_CONFIG_FREQUENCY NRF_TIMER_FREQ_62500Hz +#define TIMER1_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER1_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER1_INSTANCE_INDEX (TIMER0_ENABLED) +#endif + +#define TIMER2_ENABLED 0 + +#if (TIMER2_ENABLED == 1) +#define TIMER2_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER2_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER2_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER2_INSTANCE_INDEX (TIMER1_ENABLED+TIMER0_ENABLED) +#endif + +#define TIMER3_ENABLED 0 + +#if (TIMER3_ENABLED == 1) +#define TIMER3_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER3_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER3_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER3_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER3_INSTANCE_INDEX (TIMER2_ENABLED+TIMER2_INSTANCE_INDEX) +#endif + +#define TIMER4_ENABLED 0 + +#if (TIMER4_ENABLED == 1) +#define TIMER4_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER4_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER4_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER4_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER4_INSTANCE_INDEX (TIMER3_ENABLED+TIMER3_INSTANCE_INDEX) +#endif + + +#define TIMER_COUNT (TIMER0_ENABLED + TIMER1_ENABLED + TIMER2_ENABLED + TIMER3_ENABLED + TIMER4_ENABLED) + +/* RTC */ +#define RTC0_ENABLED 0 + +#if (RTC0_ENABLED == 1) +#define RTC0_CONFIG_FREQUENCY 32678 +#define RTC0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC0_CONFIG_RELIABLE false + +#define RTC0_INSTANCE_INDEX 0 +#endif + +#define RTC1_ENABLED 1 + +#if (RTC1_ENABLED == 1) +#define RTC1_CONFIG_FREQUENCY 128 +#define RTC1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC1_CONFIG_RELIABLE false + +#define RTC1_INSTANCE_INDEX (RTC0_ENABLED) +#endif + +#define RTC_COUNT (RTC0_ENABLED+RTC1_ENABLED) + +#define NRF_MAXIMUM_LATENCY_US 2000 + +/* RNG */ +#define RNG_ENABLED 1 + +#if (RNG_ENABLED == 1) +#define RNG_CONFIG_ERROR_CORRECTION true +#define RNG_CONFIG_POOL_SIZE 8 +#define RNG_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + +/* SPI */ +#define SPI0_ENABLED 0 + +#if (SPI0_ENABLED == 1) +#define SPI0_USE_EASY_DMA 0 + +#define SPI0_CONFIG_SCK_PIN 2 +#define SPI0_CONFIG_MOSI_PIN 3 +#define SPI0_CONFIG_MISO_PIN 4 +#define SPI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI0_INSTANCE_INDEX 0 +#endif + +#define SPI1_ENABLED 0 + +#if (SPI1_ENABLED == 1) +#define SPI1_USE_EASY_DMA 0 + +#define SPI1_CONFIG_SCK_PIN 2 +#define SPI1_CONFIG_MOSI_PIN 3 +#define SPI1_CONFIG_MISO_PIN 4 +#define SPI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI1_INSTANCE_INDEX (SPI0_ENABLED) +#endif + +#define SPI2_ENABLED 0 + +#if (SPI2_ENABLED == 1) +#define SPI2_USE_EASY_DMA 0 + +#define SPI2_CONFIG_SCK_PIN 2 +#define SPI2_CONFIG_MOSI_PIN 3 +#define SPI2_CONFIG_MISO_PIN 4 +#define SPI2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI2_INSTANCE_INDEX (SPI0_ENABLED + SPI1_ENABLED) +#endif + +#define SPI_COUNT (SPI0_ENABLED + SPI1_ENABLED + SPI2_ENABLED) + +/* UART */ +#define UART0_ENABLED 1 + +#if (UART0_ENABLED == 1) +#define UART0_CONFIG_HWFC NRF_UART_HWFC_DISABLED +#define UART0_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED +#define UART0_CONFIG_BAUDRATE NRF_UART_BAUDRATE_38400 +#define UART0_CONFIG_PSEL_TXD 6 +#define UART0_CONFIG_PSEL_RXD 8 +#define UART0_CONFIG_PSEL_CTS 7 +#define UART0_CONFIG_PSEL_RTS 5 +#define UART0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#ifdef NRF52 +#define UART0_CONFIG_USE_EASY_DMA false +//Compile time flag +#define UART_EASY_DMA_SUPPORT 1 +#define UART_LEGACY_SUPPORT 1 +#endif //NRF52 +#endif + +#define TWI0_ENABLED 0 + +#if (TWI0_ENABLED == 1) +#define TWI0_CONFIG_FREQUENCY NRF_TWI_FREQ_100K +#define TWI0_CONFIG_SCL 0 +#define TWI0_CONFIG_SDA 1 +#define TWI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + +#define TWI0_INSTANCE_INDEX 0 +#endif + +#define TWI1_ENABLED 0 + +#if (TWI1_ENABLED == 1) +#define TWI1_CONFIG_FREQUENCY NRF_TWI_FREQ_100K +#define TWI1_CONFIG_SCL 0 +#define TWI1_CONFIG_SDA 1 +#define TWI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + +#define TWI1_INSTANCE_INDEX (TWI0_ENABLED) +#endif + +#define TWI_COUNT (TWI0_ENABLED+TWI1_ENABLED) + +/* TWIS */ +#define TWIS0_ENABLED 0 + +#if (TWIS0_ENABLED == 1) + #define TWIS0_CONFIG_ADDR0 0 + #define TWIS0_CONFIG_ADDR1 0 /* 0: Disabled */ + #define TWIS0_CONFIG_SCL 0 + #define TWIS0_CONFIG_SDA 1 + #define TWIS0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + + #define TWIS0_INSTANCE_INDEX 0 +#endif + +#define TWIS1_ENABLED 0 + +#if (TWIS1_ENABLED == 1) + #define TWIS1_CONFIG_ADDR0 0 + #define TWIS1_CONFIG_ADDR1 0 /* 0: Disabled */ + #define TWIS1_CONFIG_SCL 0 + #define TWIS1_CONFIG_SDA 1 + #define TWIS1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + + #define TWIS1_INSTANCE_INDEX (TWIS0_ENABLED) +#endif + +#define TWIS_COUNT (TWIS0_ENABLED + TWIS1_ENABLED) +/* For more documentation see nrf_drv_twis.h file */ +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +/* For more documentation see nrf_drv_twis.h file */ +#define TWIS_NO_SYNC_MODE 0 +/** + * \brief Definition for patching PAN problems + * + * Set this definition to nonzero value to patch anomalies + * from MPW3 - first lunch microcontroller. + * + * Concerns: + * - PAN-29: TWIS: incorrect bits in ERRORSRC + * - PAN-30: TWIS: STOP task does not work as expected + */ +#define NRF_TWIS_PATCH_FOR_MPW3 1 + + +/* QDEC */ +#define QDEC_ENABLED 0 + +#if (QDEC_ENABLED == 1) +#define QDEC_CONFIG_REPORTPER NRF_QDEC_REPORTPER_10 +#define QDEC_CONFIG_SAMPLEPER NRF_QDEC_SAMPLEPER_16384us +#define QDEC_CONFIG_PIO_A 1 +#define QDEC_CONFIG_PIO_B 2 +#define QDEC_CONFIG_PIO_LED 3 +#define QDEC_CONFIG_LEDPRE 511 +#define QDEC_CONFIG_LEDPOL NRF_QDEC_LEPOL_ACTIVE_HIGH +#define QDEC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define QDEC_CONFIG_DBFEN false +#define QDEC_CONFIG_SAMPLE_INTEN false +#endif + +/* SAADC */ +#define SAADC_ENABLED 0 + +#if (SAADC_ENABLED == 1) +#define SAADC_CONFIG_RESOLUTION NRF_SAADC_RESOLUTION_10BIT +#define SAADC_CONFIG_OVERSAMPLE NRF_SAADC_OVERSAMPLE_DISABLED +#define SAADC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + +/* LPCOMP */ +#define LPCOMP_ENABLED 0 + +#if (LPCOMP_ENABLED == 1) +#define LPCOMP_CONFIG_REFERENCE NRF_LPCOMP_REF_SUPPLY_4_8 +#define LPCOMP_CONFIG_DETECTION NRF_LPCOMP_DETECT_DOWN +#define LPCOMP_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define LPCOMP_CONFIG_INPUT NRF_LPCOMP_INPUT_0 +#endif + +/* WDT */ +#define WDT_ENABLED 1 + +#if (WDT_ENABLED == 1) +#define WDT_CONFIG_BEHAVIOUR NRF_WDT_BEHAVIOUR_RUN_SLEEP +#define WDT_CONFIG_RELOAD_VALUE 2000 +#define WDT_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#endif + +#include "nrf_drv_config_validation.h" +#endif // NRF_DRV_CONFIG_H + +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/config/pstorage_platform.h b/platform/nrf52dk/config/pstorage_platform.h new file mode 100644 index 000000000..3102b2097 --- /dev/null +++ b/platform/nrf52dk/config/pstorage_platform.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + /** @cond To make doxygen skip this file */ + +/** @file + * This header contains defines with respect persistent storage that are specific to + * persistent storage implementation and application use case. + */ +#ifndef PSTORAGE_PL_H__ +#define PSTORAGE_PL_H__ + +#include +#include "nrf.h" + +static __INLINE uint16_t pstorage_flash_page_size() +{ + return (uint16_t)NRF_FICR->CODEPAGESIZE; +} + +#define PSTORAGE_FLASH_PAGE_SIZE pstorage_flash_page_size() /**< Size of one flash page. */ +#define PSTORAGE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */ + +#ifdef NRF51 +#define BOOTLOADER_ADDRESS (NRF_UICR->BOOTLOADERADDR) +#elif defined NRF52 +#define BOOTLOADER_ADDRESS (PSTORAGE_FLASH_EMPTY_MASK) +#endif + +#define PSTORAGE_FLASH_PAGE_END \ + ((BOOTLOADER_ADDRESS != PSTORAGE_FLASH_EMPTY_MASK) \ + ? (BOOTLOADER_ADDRESS / PSTORAGE_FLASH_PAGE_SIZE) \ + : NRF_FICR->CODESIZE) + + +#define PSTORAGE_NUM_OF_PAGES 2 /**< Number of flash pages allocated for the pstorage module excluding the swap page, configurable based on system requirements. */ +#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */ + +#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_NUM_OF_PAGES - 1) \ + * PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */ +#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */ +#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */ + +#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */ +#define PSTORAGE_CMD_QUEUE_SIZE 30 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */ + + +/** Abstracts persistently memory block identifier. */ +typedef uint32_t pstorage_block_t; + +typedef struct +{ + uint32_t module_id; /**< Module ID.*/ + pstorage_block_t block_id; /**< Block ID.*/ +} pstorage_handle_t; + +typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */ + +/**\brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */ +void pstorage_sys_event_handler (uint32_t sys_evt); + +#endif // PSTORAGE_PL_H__ + +/** @} */ +/** @endcond */ diff --git a/platform/nrf52dk/contiki-conf.h b/platform/nrf52dk/contiki-conf.h new file mode 100644 index 000000000..6303c90db --- /dev/null +++ b/platform/nrf52dk/contiki-conf.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-contikic-conf Contiki configuration + * @{ + * + * \file + * Contiki configuration for the nRF52 DK + */ +#ifndef CONTIKI_CONF_H +#define CONTIKI_CONF_H + +#include +/*---------------------------------------------------------------------------*/ +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif /* PROJECT_CONF_H */ +/*---------------------------------------------------------------------------*/ +/* Include platform peripherals configuration */ +#include "platform-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \name Network Stack Configuration + * + * @{ + */ +#ifndef NETSTACK_CONF_NETWORK +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#endif /* NETSTACK_CONF_NETWORK */ + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC ble_ipsp_mac_driver +#endif /* NETSTACK_CONF_MAC */ + +/* 6LoWPAN */ +#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /**< Always compress IPv6 packets. */ +#define SICSLOWPAN_CONF_FRAG 0 /**< We don't use 6LoWPAN fragmentation as IPSP takes care of that for us.*/ +#define SICSLOWPAN_FRAMER_HDRLEN 0 /**< Use fixed header len rather than framer.length() function */ + +/* Packet buffer */ +#define PACKETBUF_CONF_SIZE 1280 /**< Required IPv6 MTU size */ +/** @} */ + +/** + * \name BLE configuration + * @{ + */ +#ifndef DEVICE_NAME +#define DEVICE_NAME "Contiki nRF52dk" /**< Device name used in BLE undirected advertisement. */ +#endif +/** + * @} + */ + +/** + * \name IPv6 network buffer configuration + * + * @{ + */ +/* Don't let contiki-default-conf.h decide if we are an IPv6 build */ +#ifndef NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_WITH_IPV6 0 +#endif + +#if NETSTACK_CONF_WITH_IPV6 +/*---------------------------------------------------------------------------*/ +/* Addresses, Sizes and Interfaces */ +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* The size of the uIP main buffer */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1280 +#endif + +/* ND and Routing */ +#define UIP_CONF_ROUTER 0 /**< BLE master role, which allows for routing, isn't supported. */ +#define UIP_CONF_ND6_SEND_NA 1 +#define UIP_CONF_IP_FORWARD 0 /**< No packet forwarding. */ + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#endif + +#ifndef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 20 +#endif + +#ifndef UIP_CONF_TCP +#define UIP_CONF_TCP 1 +#endif + +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS 64 +#endif + +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_ICMP6 1 +#endif /* NETSTACK_CONF_WITH_IPV6 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Generic Configuration directives + * + * @{ + */ +#ifndef ENERGEST_CONF_ON +#define ENERGEST_CONF_ON 1 /**< Energest Module */ +#endif +/** @} */ +#endif /* CONTIKI_CONF_H */ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/contiki-main.c b/platform/nrf52dk/contiki-main.c new file mode 100644 index 000000000..50fcfcd28 --- /dev/null +++ b/platform/nrf52dk/contiki-main.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + */ +#include +#include + +#include "nordic_common.h" +#include "nrf_drv_config.h" +#include "nrf_drv_gpiote.h" +#ifdef SOFTDEVICE_PRESENT +#include "softdevice_handler.h" +#include "ble/ble-core.h" +#include "ble/ble-mac.h" +#endif + +#include "contiki.h" +#include "contiki-net.h" +#include "leds.h" +#include "lib/sensors.h" + +#include "dev/watchdog.h" +#include "dev/serial-line.h" +#include "dev/uart0.h" +#include "dev/lpm.h" + +#define DEBUG 0 + +#if NETSTACK_CONF_WITH_IPV6 +#include "uip-debug.h" +#include "net/ipv6/uip-ds6.h" +#else +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +#endif + +#if defined(SOFTDEVICE_PRESENT) && PLATFORM_INDICATE_BLE_STATE +PROCESS(ble_iface_observer, "BLE interface observer"); + +/** + * \brief A process that handles adding/removing + * BLE IPSP interfaces. + */ +PROCESS_THREAD(ble_iface_observer, ev, data) +{ + static struct etimer led_timer; + + PROCESS_BEGIN(); + + etimer_set(&led_timer, CLOCK_SECOND/2); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == ble_event_interface_added) { + etimer_stop(&led_timer); + leds_off(LEDS_1); + leds_on(LEDS_2); + } else if(ev == ble_event_interface_deleted) { + etimer_set(&led_timer, CLOCK_SECOND/2); + leds_off(LEDS_2); + } else if(ev == PROCESS_EVENT_TIMER && etimer_expired(&led_timer)) { + etimer_reset(&led_timer); + leds_toggle(LEDS_1); + } + } + PROCESS_END(); +} +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Board specific initialization + * + * This function will enable SoftDevice is present. + */ +static void +board_init(void) +{ +#ifdef SOFTDEVICE_PRESENT + // Initialize the SoftDevice handler module. + SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); +#endif +#ifdef PLATFORM_HAS_BUTTON + if (!nrf_drv_gpiote_is_init()) { + nrf_drv_gpiote_init(); + } +#endif +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Main function for nRF52dk platform. + * \note This function doesn't return. + */ +int +main(void) +{ + board_init(); + leds_init(); + + clock_init(); + rtimer_init(); + + watchdog_init(); + process_init(); + + // Seed value is ignored since hardware RNG is used. + random_init(0); + +#ifdef UART0_ENABLED + uart0_init(); +#if SLIP_ARCH_CONF_ENABLE + slip_arch_init(0); +#else + uart0_set_input(serial_line_input_byte); + serial_line_init(); +#endif +#endif + + PRINTF("Starting " CONTIKI_VERSION_STRING "\n"); + + process_start(&etimer_process, NULL); + ctimer_init(); + +#if ENERGEST_CONF_ON + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); +#endif + +#ifdef SOFTDEVICE_PRESENT + ble_stack_init(); + ble_advertising_init(DEVICE_NAME); + +#if NETSTACK_CONF_WITH_IPV6 + netstack_init(); + linkaddr_t linkaddr; + ble_get_mac(linkaddr.u8); + // Set link layer address + linkaddr_set_node_addr(&linkaddr); + // Set device link layer address in uip stack. + memcpy(&uip_lladdr.addr, &linkaddr, sizeof(uip_lladdr.addr)); + uip_debug_lladdr_print(&uip_lladdr); + PRINTF("\n"); + process_start(&ble_iface_observer, NULL); + process_start(&tcpip_process, NULL); +#endif /* NETSTACK_CONF_WITH_IPV6 */ +#endif /* SOFTDEVICE_PRESENT */ + + process_start(&sensors_process, NULL); + autostart_start(autostart_processes); + + watchdog_start(); + +#ifdef SOFTDEVICE_PRESENT + ble_advertising_start(); + PRINTF("Advertising name [%s]\n", DEVICE_NAME); +#endif + + while(1) { + uint8_t r; + do { + r = process_run(); + watchdog_periodic(); + } while(r > 0); + + lpm_drop(); + } +} +/** + * @} + */ diff --git a/platform/nrf52dk/dbg-io/dbg.c b/platform/nrf52dk/dbg-io/dbg.c new file mode 100644 index 000000000..db9bb63c0 --- /dev/null +++ b/platform/nrf52dk/dbg-io/dbg.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * Function implementations for debug io module. + * \author + * Wojciech Bober + * + */ +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +unsigned int +dbg_send_bytes(const unsigned char *s, unsigned int len) +{ + unsigned int i = 0; + + while (s && *s != 0) { + if (i >= len) { + break; + } + uart0_writeb(*s++); + i++; + } + + return i; +} +/*---------------------------------------------------------------------------*/ +int +dbg_putchar(int c) +{ + uart0_writeb(c); + return c; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dbg-io/dbg.h b/platform/nrf52dk/dbg-io/dbg.h new file mode 100644 index 000000000..7c623336b --- /dev/null +++ b/platform/nrf52dk/dbg-io/dbg.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * +3 * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * Header file for the debug module. + * \author + * Wojciech Bober + * + */ +#ifndef DBG_H_ +#define DBG_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Print a stream of bytes + * \param seq A pointer to the stream + * \param len The number of bytes to print + * \return The number of printed bytes + */ +unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/** + * \brief Print a character to debug output + * \param c Character to print + * \return Printed character + */ +int dbg_putchar(int c); +/*---------------------------------------------------------------------------*/ +#endif /* DBG_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dbg-io/debug-uart.h b/platform/nrf52dk/dbg-io/debug-uart.h new file mode 100644 index 000000000..b52d2fb50 --- /dev/null +++ b/platform/nrf52dk/dbg-io/debug-uart.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * A header file to maintain compatibility with DBG I/O. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef DEBUG_UART_H_ +#define DEBUG_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "dbg.h" +/*---------------------------------------------------------------------------*/ +#endif /* DEBUG_UART_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/button-sensor.c b/platform/nrf52dk/dev/button-sensor.c new file mode 100644 index 000000000..3c218a439 --- /dev/null +++ b/platform/nrf52dk/dev/button-sensor.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``as-is'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-button Buttons driver + * @{ + * + * \file + * Driver for nRF52 DK buttons. + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include "nordic_common.h" +#include "nrf_drv_gpiote.h" +#include "nrf_assert.h" +#include "boards.h" +#include "contiki.h" +#include "lib/sensors.h" +#include "button-sensor.h" + +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) /**< Delay before button state is assumed to be stable */ + +/*---------------------------------------------------------------------------*/ +struct btn_timer +{ + struct timer debounce; + clock_time_t start; + clock_time_t duration; +}; + +static struct btn_timer btn_timer[BUTTONS_NUMBER]; +static int btn_state = 0; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Button toggle handler + * \param pin GPIO pin which has been triggered + * \param action toggle direction + * + */ +static void +gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) +{ + int id = pin - BUTTON_START; + + if(!timer_expired(&(btn_timer[id].debounce))) { + return; + } + + /* Set timer to ignore consecutive changes for + * DEBOUNCE_DURATION. + */ + timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); + + /* + * Start measuring duration on falling edge, stop on rising edge. + */ + if(nrf_drv_gpiote_in_is_set(pin) == 0) { + btn_timer[id].start = clock_time(); + btn_timer[id].duration = 0; + } else { + btn_timer[id].duration = clock_time() - btn_timer[id].start; + } + sensors_changed(&buttons[id]); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the button sensor for all buttons. + * + * \param type if \a SENSORS_HW_INIT is passed the function will initialize + * given button + * if \a SENSORS_ACTIVE is passed then \p c parameter defines + * whether button should be set active or inactive + * \param c 0 to disable the button, non-zero: enable + * \param pin GPIOE pin number + */ +static int +config(int type, int c, nrf_drv_gpiote_pin_t pin) +{ + int id = pin - BUTTON_START; + + switch(type) { + case SENSORS_HW_INIT: { + nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); + config.pull = NRF_GPIO_PIN_PULLUP; + nrf_drv_gpiote_in_init(pin, &config, gpiote_event_handler); + timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); + return 1; + } + case SENSORS_ACTIVE: { + if(c) { + nrf_drv_gpiote_in_event_enable(pin, true); + btn_state |= (1 << id); + } else { + nrf_drv_gpiote_in_event_disable(pin); + btn_state &= ~(1 << id); + } + return 1; + } + default: + return 0; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 1 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_1(int type, int value) +{ + return config(type, value, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 2 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_2(int type, int value) +{ + return config(type, value, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 3 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_3(int type, int value) +{ + return config(type, value, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 4 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_4(int type, int value) +{ + return config(type, value, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button + * \param type pass \ref BUTTON_SENSOR_VALUE_STATE to get current button state + * or \ref BUTTON_SENSOR_VALUE_DURATION to get active state duration + * \param pin GPIOE pin number + * + * \retval BUTTON_SENSOR_VALUE_PRESSED + * \retval BUTTON_SENSOR_VALUE_RELEASED when \a type is \ref BUTTON_SENSOR_VALUE_STATE + * \retval duration Active state duration in clock ticks + */ +static int +value(int type, nrf_drv_gpiote_pin_t pin) +{ + + if(type == BUTTON_SENSOR_VALUE_STATE) { + return nrf_drv_gpiote_in_is_set(pin) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return btn_timer[pin - BUTTON_START].duration; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 1 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_1(int type) +{ + return value(type, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 2 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_2(int type) +{ + return value(type, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 3 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_3(int type) +{ + return value(type, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 4 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_4(int type) +{ + return value(type, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Get status of a given button + * \param type \a SENSORS_ACTIVE or \a SENSORS_READY + * \param pin GPIOE pin number + * \return 1 if the button's port interrupt is enabled + */ +static int +status(int type, nrf_drv_gpiote_pin_t pin) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return (btn_state & (1 << (pin - BUTTON_START))); + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 1 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_1(int type) +{ + return status(type, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 2 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_2(int type) +{ + return status(type, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 3 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_3(int type) +{ + return status(type, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 3 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_4(int type) +{ + return status(type, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +const struct sensors_sensor buttons[BUTTONS_NUMBER] = { + {BUTTON_SENSOR, value_button_1, config_button_1, status_button_1}, + {BUTTON_SENSOR, value_button_2, config_button_2, status_button_2}, + {BUTTON_SENSOR, value_button_3, config_button_3, status_button_3}, + {BUTTON_SENSOR, value_button_4, config_button_4, status_button_4}, }; +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/button-sensor.h b/platform/nrf52dk/dev/button-sensor.h new file mode 100644 index 000000000..ababb1c1c --- /dev/null +++ b/platform/nrf52dk/dev/button-sensor.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-button Buttons driver + * @{ + * + * \file + * Header file for the nRF52dk button driver. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_VALUE_STATE 0 /**< Can be passed to value() function + to get current button state */ +#define BUTTON_SENSOR_VALUE_DURATION 1 /**< Can be passed to value() function + to get low state duration */ + +#define BUTTON_SENSOR_VALUE_RELEASED 0 +#define BUTTON_SENSOR_VALUE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor buttons[]; +/*---------------------------------------------------------------------------*/ +#define button_1 buttons[0] +#define button_2 buttons[1] +#define button_3 buttons[2] +#define button_4 buttons[3] +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/leds-arch.c b/platform/nrf52dk/dev/leds-arch.c new file mode 100644 index 000000000..019589493 --- /dev/null +++ b/platform/nrf52dk/dev/leds-arch.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-led LED driver + * @{ + * + * \file + * Architecture specific LED driver implementation for nRF52 DK. + * \author + * Wojciech Bober + */ +#include "boards.h" +#include "contiki.h" +#include "dev/leds.h" + +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + LEDS_CONFIGURE(LEDS_MASK); + LEDS_OFF(LEDS_MASK); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return (unsigned char)(LED_IS_ON(LEDS_MASK) >> LED_START); +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + unsigned int mask = (unsigned int)leds << LED_START; + LEDS_OFF(LEDS_MASK); + LEDS_ON(mask); +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/nrf52dk-sensors.c b/platform/nrf52dk/dev/nrf52dk-sensors.c new file mode 100644 index 000000000..3d56e91d1 --- /dev/null +++ b/platform/nrf52dk/dev/nrf52dk-sensors.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-sensors Sensors + * The nRF52 DK exports 4 button sensors and an internal temperature sensor. + * @{ + * + * \file + * This file exports a global sensors table. + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/temperature-sensor.h" +/*---------------------------------------------------------------------------*/ +SENSORS( + &button_1, + &button_2, + &button_3, + &button_4, + &temperature_sensor +); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/temperature-sensor.c b/platform/nrf52dk/dev/temperature-sensor.c new file mode 100644 index 000000000..5aac8b3ef --- /dev/null +++ b/platform/nrf52dk/dev/temperature-sensor.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-temp Temperature sensor driver + * This is a driver for nRF52832 hardware sensor. + * + * @{ + * + * \file + * Temperature sensor implementation. + * \author + * Wojciech Bober + * + */ +#ifndef SOFTDEVICE_PRESENT +#include "nrf_temp.h" +#else +#include "nrf_soc.h" +#endif +#include "contiki.h" +#include "dev/temperature-sensor.h" + + +const struct sensors_sensor temperature_sensor; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns device temperature + * \param type ignored + * \return Device temperature in degrees Celsius + */ +static int +value(int type) +{ +#ifndef SOFTDEVICE_PRESENT + return nrf_temp_read(); +#else + int32_t temp; + sd_temp_get(&temp); + return temp >> 2; +#endif +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configures temperature sensor + * \param type initializes the hardware sensor when \a type is set to + * \a SENSORS_HW_INIT + * \param c ignored + * \return 1 + * \note This function does nothing when SoftDevice is present + */ +static int +configure(int type, int c) +{ +#ifndef SOFTDEVICE_PRESENT + if (type == SENSORS_HW_INIT) { + nrf_temp_init(); + } +#endif + return 1; +} +/** + * \brief Return temperature sensor status + * \param type ignored + * \return 1 + */ +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(temperature_sensor, TEMPERATURE_SENSOR, value, configure, status); +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/temperature-sensor.h b/platform/nrf52dk/dev/temperature-sensor.h new file mode 100644 index 000000000..27b246b2d --- /dev/null +++ b/platform/nrf52dk/dev/temperature-sensor.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-temp Temperature sensor driver + * @{ + * + * \file + * Temperature sensor header file. + * \author + * Wojciech Bober + * + */ + +#ifndef TEMPERATURE_SENSOR_H_ +#define TEMPERATURE_SENSOR_H_ + +#include "lib/sensors.h" + +extern const struct sensors_sensor temperature_sensor; + +#define TEMPERATURE_SENSOR "Temperature" + +#endif /* TEMPERATURE_SENSOR_H_ */ + +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/platform-conf.h b/platform/nrf52dk/platform-conf.h new file mode 100644 index 000000000..931a3c275 --- /dev/null +++ b/platform/nrf52dk/platform-conf.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup platform + * @{ + * + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + * + * \addtogroup nrf52dk-platform-conf Platform configuration + * @{ + * \file + * Platform features configuration. + * \author + * Wojciech Bober + * + */ +#ifndef PLATFORM_CONF_H_ +#define PLATFORM_CONF_H_ + +#include "boards.h" + +#define PLATFORM_HAS_BATTERY 0 +#define PLATFORM_HAS_RADIO 0 +#define PLATFORM_HAS_TEMPERATURE 1 + +/** + * \name Leds configurations + * + * On nRF52dk all leds are green. + * + * @{ + */ +#define PLATFORM_HAS_LEDS 1 + +#define LEDS_1 (1 << (LED_1 - LED_START)) // 1 +#define LEDS_2 (1 << (LED_2 - LED_START)) // 2 +#define LEDS_3 (1 << (LED_3 - LED_START)) // 4 +#define LEDS_4 (1 << (LED_4 - LED_START)) // 8 + +#define LEDS_GREEN LEDS_1 +#define LEDS_YELLOW LEDS_2 +#define LEDS_RED LEDS_3 +#define LEDS_BLUE LEDS_4 + +#define LEDS_CONF_ALL (LEDS_1 | LEDS_2 | LEDS_3 | LEDS_4) + +/** + * \brief If set to 1 then LED1 and LED2 are used by the + * platform to indicate BLE connection state. + */ +#define PLATFORM_INDICATE_BLE_STATE 1 +/** @} */ + +/** + * \name Button configurations + * + * @{ + */ +/* Notify various examples that we have Buttons */ +#define PLATFORM_HAS_BUTTON 1 + +/* + * Override button symbols from dev/button-sensor.h, for the examples that + * include it + */ +#define button_sensor button_1 +#define button_sensor2 button_2 + +/** + * \brief nRF52 RTC instance to be used for Contiki clock driver. + * \note RTC 0 is used by the SoftDevice. + */ +#define PLATFORM_RTC_INSTANCE_ID 1 + +/** + * \brief nRF52 timer instance to be used for Contiki rtimer driver. + * \note Timer 0 is used by the SoftDevice. + */ +#define PLATFORM_TIMER_INSTANCE_ID 1 + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Compiler configuration and platform-specific type definitions + * + * Those values are not meant to be modified by the user + * @{ + */ +#define CLOCK_CONF_SECOND 128 + +/* Compiler configurations */ +#define CCIF +#define CLIF + +/* Platform typedefs */ +typedef uint32_t clock_time_t; +typedef uint32_t uip_stats_t; + +/* Clock (time) comparison macro */ +#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) + +#define RTIMER_ARCH_SECOND 62500 +/* + * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define + * RTIMER_CLOCK_LT to override this + */ +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** @} + * @} + * @} + */ +#endif /* PLATFORM_CONF_H_ */ diff --git a/platform/nrf52dk/rtt/rtt-printf.c b/platform/nrf52dk/rtt/rtt-printf.c new file mode 100644 index 000000000..416fff0ab --- /dev/null +++ b/platform/nrf52dk/rtt/rtt-printf.c @@ -0,0 +1,24 @@ +#include +#include "segger-rtt.h" + +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +int +putchar(int c) +{ + SEGGER_RTT_Write(0, &c, 1); + return c; +} + +int +printf(const char *fmt, ...) +{ + int res; + va_list ap; + va_start(ap, fmt); + res = SEGGER_RTT_vprintf(0, fmt, &ap); + va_end(ap); + return res; +} + + diff --git a/platform/nrf52dk/rtt/segger-rtt-conf.h b/platform/nrf52dk/rtt/segger-rtt-conf.h new file mode 100644 index 000000000..ac996644f --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt-conf.h @@ -0,0 +1,135 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +---------------------------------------------------------------------- +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +---------------------------END-OF-HEADER------------------------------ +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __ICCARM__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) + +#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) + #ifdef __ARM_ARCH_6M__ + #define SEGGER_RTT_LOCK(SavedState) { \ + asm volatile ("mrs %0, primask \n\t" \ + "mov r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (SavedState) \ + : \ + : "r1" \ + ); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (SavedState) \ + : \ + ); \ + } + + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, $128 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (SavedState) \ + : \ + : "r1" \ + ); \ + } + #define SEGGER_RTT_UNLOCK(SavedState) { \ + asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (SavedState) \ + : \ + ); \ + } + #else + #define SEGGER_RTT_LOCK(SavedState) (void)(SavedState) + #define SEGGER_RTT_UNLOCK(SavedState) (void)(SavedState) + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + SavedState = __get_PRIMASK(); \ + __set_PRIMASK(1); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + __set_PRIMASK(SavedState); \ + } + #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + SavedState = __get_BASEPRI(); \ + __set_BASEPRI(128); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + __set_BASEPRI(SavedState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK(SavedState) (void)(SavedState) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK(SavedState) (void)(SavedState) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt-printf.c b/platform/nrf52dk/rtt/segger-rtt-printf.c new file mode 100644 index 000000000..e992e7a36 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt-printf.c @@ -0,0 +1,510 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_printf.c +Purpose : Replacement for printf to write formatted data via RTT +---------------------------------------------------------------------- +*/ +#include "segger-rtt.h" +#include "segger-rtt-conf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) +#endif + +#include +#include + + +#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define FORMAT_FLAG_PAD_ZERO (1u << 1) +#define FORMAT_FLAG_PRINT_SIGN (1u << 2) +#define FORMAT_FLAG_ALTERNATE (1u << 3) + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +typedef struct { + char* pBuffer; + unsigned BufferSize; + unsigned Cnt; + + int ReturnValue; + + unsigned RTTBufferIndex; +} SEGGER_RTT_PRINTF_DESC; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Static code +* +********************************************************************** +*/ +/********************************************************************* +* +* _StoreChar +*/ +static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { + unsigned Cnt; + + Cnt = p->Cnt; + if ((Cnt + 1u) <= p->BufferSize) { + *(p->pBuffer + Cnt) = c; + p->Cnt = Cnt + 1u; + p->ReturnValue++; + } + // + // Write part of string, when the buffer is full + // + if (p->Cnt == p->BufferSize) { + if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { + p->ReturnValue = -1; + } else { + p->Cnt = 0u; + } + } +} + +/********************************************************************* +* +* _PrintUnsigned +*/ +static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned Div; + unsigned Digit; + unsigned Number; + unsigned Width; + char c; + + Number = v; + Digit = 1u; + // + // Get actual field width + // + Width = 1u; + while (Number >= Base) { + Number = (Number / Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { + if (FieldWidth != 0u) { + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { + c = '0'; + } else { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, c); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Compute Digit. + // Loop until Digit has the value of the highest digit required. + // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + // + while (1) { + if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) + NumDigits--; + } else { + Div = v / Digit; + if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done + break; + } + } + Digit *= Base; + } + // + // Output digits + // + do { + Div = v / Digit; + v -= Div * Digit; + _StoreChar(pBufferDesc, _aV2C[Div]); + if (pBufferDesc->ReturnValue < 0) { + break; + } + Digit /= Base; + } while (Digit); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + } +} + +/********************************************************************* +* +* _PrintInt +*/ +static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + unsigned Width; + int Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int)Base) { + Number = (Number / (int)Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { + FieldWidth--; + } + + // + // Print leading spaces if necessary + // + if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + // + // Print sign if necessary + // + if (pBufferDesc->ReturnValue >= 0) { + if (v < 0) { + v = -v; + _StoreChar(pBufferDesc, '-'); + } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { + _StoreChar(pBufferDesc, '+'); + } else { + + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print leading zeros if necessary + // + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, '0'); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print number without sign + // + _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); + } + } + } +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_vprintf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string +* pParamList Pointer to the list of arguments for the format string +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { + char c; + SEGGER_RTT_PRINTF_DESC BufferDesc; + int v; + unsigned NumDigits; + unsigned FormatFlags; + unsigned FieldWidth; + char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; + + BufferDesc.pBuffer = acBuffer; + BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; + BufferDesc.Cnt = 0u; + BufferDesc.RTTBufferIndex = BufferIndex; + BufferDesc.ReturnValue = 0; + + do { + c = *sFormat; + sFormat++; + if (c == 0u) { + break; + } + if (c == '%') { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + do { + c = *sFormat; + switch (c) { + case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; + case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; + case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; + case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; + default: v = 0; break; + } + } while (v); + // + // filter out field with + // + FieldWidth = 0u; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *sFormat; + if (c == '.') { + sFormat++; + do { + c = *sFormat; + if (c == '*') { + sFormat++; + v = va_arg(*pParamList, int); + NumDigits = (unsigned)v; + break; + } + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + NumDigits = NumDigits * 10u + ((unsigned)c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *sFormat; + do { + if ((c == 'l') || (c == 'h')) { + c = *sFormat; + sFormat++; + } else { + break; + } + } while (1); + // + // Handle specifiers + // + switch (c) { + case 'c': { + char c0; + v = va_arg(*pParamList, int); + c0 = (char)v; + _StoreChar(&BufferDesc, c0); + break; + } + case 'd': + v = va_arg(*pParamList, int); + _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'u': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); + break; + case 's': + { + const char * s = va_arg(*pParamList, const char *); + if (NumDigits > 0) { + do { + c = *s; + s++; + if (NumDigits == 0) { + break; + } + NumDigits--; + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } else { + do { + c = *s; + s++; + if (c == '\0' || NumDigits == 0) { + break; + } + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } + } + break; + case 'p': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); + break; + case '%': + _StoreChar(&BufferDesc, '%'); + break; + default: + break; + } + sFormat++; + } else { + _StoreChar(&BufferDesc, c); + } + } while (BufferDesc.ReturnValue >= 0); + + if (BufferDesc.ReturnValue > 0) { + // + // Write remaining data, if any + // + if (BufferDesc.Cnt != 0u) { + SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); + } + BufferDesc.ReturnValue += (int)BufferDesc.Cnt; + } + return BufferDesc.ReturnValue; +} + +/********************************************************************* +* +* SEGGER_RTT_printf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string, followed by the arguments for conversion +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +* +* Notes +* (1) Conversion specifications have following syntax: +* %[flags][FieldWidth][.Precision]ConversionSpecifier +* (2) Supported flags: +* -: Left justify within the field width +* +: Always print sign extension for signed conversions +* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision +* Supported conversion specifiers: +* c: Print the argument as one char +* d: Print the argument as a signed integer +* u: Print the argument as an unsigned integer +* x: Print the argument as an hexadecimal integer +* s: Print the string pointed to by the argument +* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { + va_list ParamList; + + va_start(ParamList, sFormat); + return SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); +} +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt.c b/platform/nrf52dk/rtt/segger-rtt.c new file mode 100644 index 000000000..453a6a0e4 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt.c @@ -0,0 +1,1102 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + +---------------------------------------------------------------------- +*/ + +#include "segger-rtt.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK(SavedState) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK(SavedState) +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef MEMCPY + #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// Allocate buffers for channel 0 +// +static char _acUpBuffer [BUFFER_SIZE_UP]; +static char _acDownBuffer[BUFFER_SIZE_DOWN]; +// +// Initialize SEGGER Real-time-Terminal control block (CB) +// +SEGGER_RTT_CB _SEGGER_RTT; + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_RING_BUFFER *pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); + memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_RING_BUFFER *pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + NumBytesAtOnce = Rem; + memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_RING_BUFFER *pRing, char TerminalId) { + char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[(int)TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_RING_BUFFER *pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_RING_BUFFER* pRing; + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + volatile unsigned SavedState; + // + SEGGER_RTT_LOCK(SavedState); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_RING_BUFFER* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, Rem); + memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_RING_BUFFER *pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + volatile unsigned SavedState; + // + INIT(); + SEGGER_RTT_LOCK(SavedState); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, depending on configuration, +* remaining characters may be dropped or RTT module waits until there is more space in the buffer. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_RING_BUFFER *pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(SavedState); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(SavedState); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(SavedState); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(SavedState); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + INIT(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + char ac[2]; + SEGGER_RTT_RING_BUFFER *pRing; + volatile unsigned SavedState; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFU; + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(int)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(SavedState); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(SavedState); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_RING_BUFFER *pRing; + volatile unsigned SavedState; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = strlen(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(SavedState); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt.h b/platform/nrf52dk/rtt/segger-rtt.h new file mode 100644 index 000000000..e3436c462 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt.h @@ -0,0 +1,204 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "segger-rtt-conf.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up- (T->H) or down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by either host (down-buffer) or target (up-buffer). Must be volatile since it may be modified by host (down-buffer) + volatile unsigned RdOff; // Position of next item to be read by target (down-buffer) or host (up-buffer). Must be volatile since it may be modified by host (up-buffer) + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_RING_BUFFER; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_RING_BUFFER aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_RING_BUFFER aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3U) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "\e[0m" // Reset to default colors +#define RTT_CTRL_CLEAR "\e[2J" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "\e[2;30m" +#define RTT_CTRL_TEXT_RED "\e[2;31m" +#define RTT_CTRL_TEXT_GREEN "\e[2;32m" +#define RTT_CTRL_TEXT_YELLOW "\e[2;33m" +#define RTT_CTRL_TEXT_BLUE "\e[2;34m" +#define RTT_CTRL_TEXT_MAGENTA "\e[2;35m" +#define RTT_CTRL_TEXT_CYAN "\e[2;36m" +#define RTT_CTRL_TEXT_WHITE "\e[2;37m" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "\e[1;30m" +#define RTT_CTRL_TEXT_BRIGHT_RED "\e[1;31m" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "\e[1;32m" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\e[1;33m" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "\e[1;34m" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\e[1;35m" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "\e[1;36m" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "\e[1;37m" + +#define RTT_CTRL_BG_BLACK "\e[24;40m" +#define RTT_CTRL_BG_RED "\e[24;41m" +#define RTT_CTRL_BG_GREEN "\e[24;42m" +#define RTT_CTRL_BG_YELLOW "\e[24;43m" +#define RTT_CTRL_BG_BLUE "\e[24;44m" +#define RTT_CTRL_BG_MAGENTA "\e[24;45m" +#define RTT_CTRL_BG_CYAN "\e[24;46m" +#define RTT_CTRL_BG_WHITE "\e[24;47m" + +#define RTT_CTRL_BG_BRIGHT_BLACK "\e[4;40m" +#define RTT_CTRL_BG_BRIGHT_RED "\e[4;41m" +#define RTT_CTRL_BG_BRIGHT_GREEN "\e[4;42m" +#define RTT_CTRL_BG_BRIGHT_YELLOW "\e[4;43m" +#define RTT_CTRL_BG_BRIGHT_BLUE "\e[4;44m" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "\e[4;45m" +#define RTT_CTRL_BG_BRIGHT_CYAN "\e[4;46m" +#define RTT_CTRL_BG_BRIGHT_WHITE "\e[4;47m" + + +#endif + +/*************************** End of file ****************************/