Commit b14a851d authored by Carsten Herrmann's avatar Carsten Herrmann

added support for nRF52840 DK (PCA10056)

minor updates (internal)
parent b1f0bde1
Copyright (c) 2018, Networked Embedded Systems Lab, TU Dresden
Copyright (c) 2018 - 2019, Networked Embedded Systems Lab, TU Dresden
All rights reserved.
Redistribution and use in source and binary forms, with or without
......
......@@ -24,19 +24,20 @@ To learn more about Mixer, please check out https://mixer.nes-lab.org
Mixer encapsulates a number of critical timing constraints and exploits hardware-specific features for efficiency.
As a consequence, it contains a certain amount of low-level code and requires platform-specific adaptions.
Right now we support TelosB-compliant devices such as the Tmote Sky. Mixer ports for other platforms (e.g., based on ARM Cortex-M) will follow soon.
Right now we support TelosB-compliant devices such as the Tmote Sky as well as Nordic Semiconductor's nRF52840 DK development boards powered by the ARM Cortex-M4 based nRF52840.
Mixer ports for other platforms (e.g., based on ARM Cortex-M) will follow.
As a starting point, we provide a tutorial project that includes a simple demo application.
After installing the toolchain, it runs out-of-the-box and provides a quick understanding of the main functions and settings needed to use Mixer.
See the corresponding [readme file](tutorial/tmote/README.md) for more information.
As a starting point, we provide a tutorial project for each supported platform that includes a simple demo application.
After installing the corresponding toolchain, it runs out-of-the-box and provides a quick understanding of the main functions and settings needed to use Mixer.
See the corresponding readme files ([TelosB](tutorial/tmote/README.md), [nRF52840](tutorial/nrf52840_ses/README.md)) for more information.
## Documentation
While the TelosB port of Mixer is available right now, its documentation is still in progress.
While the TelosB and nRF52840 ports of Mixer are available right now, their documentation is still in progress.
At this moment we are heavily pushing the development of Mixer toward a complete, modular software package including detailed documentation.
Stay tuned and come back once in while to keep up to date!
In the meantime, please look into the tutorial project or visit https://mixer.nes-lab.org to learn more about Mixer.
In the meantime, please look into the tutorial projects or visit https://mixer.nes-lab.org to learn more about Mixer.
## Research
......
/***************************************************************************************************
***************************************************************************************************
*
* Copyright (c) 2019, Networked Embedded Systems Lab, TU Dresden
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the NES Lab or TU Dresden 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 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 THE COPYRIGHT HOLDER 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.
*
***********************************************************************************************//**
*
* @file gpi/arm/armv7-m/interrupts.h
*
* @brief basic interrupt handling
*
* @version $Id$
* @date TODO
*
* @author Carsten Herrmann
*
***************************************************************************************************
@details
TODO
**************************************************************************************************/
#ifndef __GPI_ARM_ARMv7M_INTERRUPTS_H__
#define __GPI_ARM_ARMv7M_INTERRUPTS_H__
//**************************************************************************************************
//***** Includes ***********************************************************************************
#include "gpi/platform_spec.h"
#include GPI_PLATFORM_PATH(cmsis_device.h)
#include "gpi/tools.h"
#ifdef GPI_SETUP_FILE
#include STRINGIFY(GPI_SETUP_FILE)
#endif
// this file is for ARMv7-M (it does not support ARMv6-M)
#if !GPI_ARCH_IS_CORE(ARMv7M)
#error unsupported architecture
#endif
//**************************************************************************************************
//***** Global (Public) Defines and Consts *********************************************************
//**************************************************************************************************
//***** Local (Private) Defines and Consts *********************************************************
// Since ARMv7-M there are specific instructions (load/store exclusive) to support unblocking
// synchronization. However, due to some implementation dependent details the usage of these
// instructions may be less efficient than the "classic" int-lock variant (depending on the
// application). So in case of problems it maybe an option to switch to the int-lock variant.
//
// (For details see "ARM Synchronization Primitives" (doc. DHT0008A ID081709). Critical points
// include the "Exclusives Reservation Granule", statements like "A local monitor can be
// implemented to tag an address for exclusive use, or it can contain a state machine that only
// tracks the issuing of Load-Exclusive and Store-Exclusive instructions.", as well as the
// question on what happens if the memory address gets overwritten by a standard write
// instruction between load/store-exclusive. Also, the Cortex-M4 User Guide (DUI0553A ID121610)
// says on page 3-36 that "The result of executing a Store-Exclusive instruction to an address
// that is different from that used in the preceding Load-Exclusive instruction is
// unpredictable." This must be wrong (because otherwise the whole concept would be
// inapplicable; I guess it refers only to the status return value, not the whole behavior),
// but a (detailed) description of the real behavior is missing.)
//
#ifndef _GPI_ARM_USE_UNBLOCKING_SYNC
#define _GPI_ARM_USE_UNBLOCKING_SYNC 1
#endif
//**************************************************************************************************
//***** Forward Class and Struct Declarations ******************************************************
//**************************************************************************************************
//***** Global Typedefs and Class Declarations *****************************************************
//**************************************************************************************************
//***** Global Variables ***************************************************************************
//**************************************************************************************************
//***** Prototypes of Global Functions *************************************************************
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
//**************************************************************************************************
//***** Implementations of Inline Functions ********************************************************
// available intrinsics: __disable_irq (-> cpsid i), __enable_irq (-> cpsie i)
static ALWAYS_INLINE void gpi_int_enable() { __enable_irq(); }
static ALWAYS_INLINE void gpi_int_disable() { __disable_irq(); }
//**************************************************************************************************
static ALWAYS_INLINE int gpi_int_lock()
{
register int ie;
REORDER_BARRIER();
// NOTE: We do not use CMSIS functions at this point to avoid spill code in debug builds.
// This may be a matter of taste (it is not absolutely necessary if performance is secondary).
__asm__ volatile
(
"mrs %0, PRIMASK \n" // ie = __get_PRIMASK()
"cpsid i \n" // __set_PRIMASK(0) / __disable_irq()
: "=r"(ie)
);
REORDER_BARRIER();
__DMB();
return ie;
}
//**************************************************************************************************
static ALWAYS_INLINE void gpi_int_unlock(int ie)
{
REORDER_BARRIER();
__DMB();
// NOTE: we expect ie as it has been returned by gpi_int_lock()
__set_PRIMASK(ie);
REORDER_BARRIER();
}
//**************************************************************************************************
static ALWAYS_INLINE void gpi_atomic_or(volatile unsigned int *p, unsigned int mask)
{
#if _GPI_ARM_USE_UNBLOCKING_SYNC
register int tmp1, tmp2;
REORDER_BARRIER();
__DMB();
__asm__
(
"1: \n"
"ldrex %1, %0 \n"
"orr %1, %1, %3 \n"
"strex %2, %1, %0 \n" // ATTENTION: Rd must be different from Rt and Rn
"cmp %2, #0 \n"
"bne 1b \n"
"dmb \n"
: "+m"(*p), "=&r"(tmp1), "=r"(tmp2)
: "r"(mask)
: "cc"
);
REORDER_BARRIER();
#else
register int ie = gpi_int_lock();
*p |= mask;
gpi_int_unlock(ie);
#endif
}
//**************************************************************************************************
static ALWAYS_INLINE void gpi_atomic_and(volatile unsigned int *p, unsigned int mask)
{
#if _GPI_ARM_USE_UNBLOCKING_SYNC
register int tmp1, tmp2;
REORDER_BARRIER();
__DMB();
__asm__
(
"1: \n"
"ldrex %1, %0 \n"
"and %1, %1, %3 \n"
"strex %2, %1, %0 \n" // ATTENTION: Rd must be different from Rt and Rn
"cmp %2, #0 \n"
"bne 1b \n"
"dmb \n"
: "+m"(*p), "=&r"(tmp1), "=r"(tmp2)
: "r"(mask)
: "cc"
);
REORDER_BARRIER();
#else
register int ie = gpi_int_lock();
*p &= mask;
gpi_int_unlock(ie);
#endif
}
//**************************************************************************************************
static ALWAYS_INLINE void gpi_atomic_set(volatile unsigned int *p, unsigned int mask)
{
gpi_atomic_or(p, mask);
}
//**************************************************************************************************
static ALWAYS_INLINE void gpi_atomic_clear(volatile unsigned int *p, unsigned int mask)
{
// if performance is extremely critical, one can copy the code from gpi_atomic_and()
// and replace "and" by "bic" instead of manually inverting the mask as done here
gpi_atomic_and(p, ~mask);
}
//**************************************************************************************************
//**************************************************************************************************
#endif // __GPI_ARM_ARMv7M_INTERRUPTS_H__
/***************************************************************************************************
***************************************************************************************************
*
* Copyright (c) 2019, Networked Embedded Systems Lab, TU Dresden
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the NES Lab or TU Dresden 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 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 THE COPYRIGHT HOLDER 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.
*
***********************************************************************************************//**
*
* @file gpi/arm/armv7-m/olf.c
*
* @brief optimized low-level functions, tuned for ARMv7-M
*
* @version $Id$
* @date TODO
*
* @author Carsten Herrmann
*
***************************************************************************************************
@details
TODO
**************************************************************************************************/
//***** Trace Settings *****************************************************************************
//**************************************************************************************************
//**** Includes ************************************************************************************
#include "gpi/olf.h"
//**************************************************************************************************
//***** Local Defines and Consts *******************************************************************
//**************************************************************************************************
//***** Local Typedefs and Class Declarations ******************************************************
//**************************************************************************************************
//***** Forward Declarations ***********************************************************************
//**************************************************************************************************
//***** Local (Static) Variables *******************************************************************
//**************************************************************************************************
//***** Global Variables ***************************************************************************
#define LT2(n) n, n+1, n+1, n+2
#define LT4(n) LT2(n), LT2(n+1), LT2(n+1), LT2(n+2)
#define LT6(n) LT4(n), LT4(n+1), LT4(n+1), LT4(n+2)
const uint8_t gpi_popcnt_lut[256] =
{
LT6(0), LT6(1), LT6(1), LT6(2)
};
#undef LT2
#undef LT4
#undef LT6
//**************************************************************************************************
//***** Local Functions ****************************************************************************
//**************************************************************************************************
//***** Global Functions ***************************************************************************
//**************************************************************************************************
//**************************************************************************************************
This diff is collapsed.
/***************************************************************************************************
***************************************************************************************************
*
* Copyright (c) 2018, Networked Embedded Systems Lab, TU Dresden
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the NES Lab or TU Dresden 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 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 THE COPYRIGHT HOLDER 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.
*
***********************************************************************************************//**
*
* @file gpi/arm/armv7-m/profile.c
*
* @brief support for program execution time profiling
*
* @version $Id$
* @date TODO
*
* @author Carsten Herrmann
*
***************************************************************************************************
@details
TODO
**************************************************************************************************/
//***** Trace Settings *****************************************************************************
//**************************************************************************************************
//**** Includes ************************************************************************************
#include "gpi/profile.h"
#include "gpi/interrupts.h"
//**************************************************************************************************
//***** Local Defines and Consts *******************************************************************
//**************************************************************************************************
//***** Local Typedefs and Class Declarations ******************************************************
//**************************************************************************************************
//***** Forward Declarations ***********************************************************************
//**************************************************************************************************
//***** Local (Static) Variables *******************************************************************
//**************************************************************************************************
//***** Global Variables ***************************************************************************
Gpi_Profile_Desc gpi_profile_desc_anchor
= {&gpi_profile_desc_anchor, &gpi_profile_desc_anchor, 0, 0, 0};
//**************************************************************************************************
//***** Local Functions ****************************************************************************
//**************************************************************************************************
//***** Global Functions ***************************************************************************
// read next valid timestamp and update ticket
int_fast8_t gpi_profile_read(Gpi_Profile_Ticket *ticket, const char **name, uint16_t *line, uint32_t *timestamp)
{
if (0 == ticket->desc)
{
ticket->desc = gpi_profile_desc_anchor.next;
ticket->index = 0;
}
while (ticket->desc != &gpi_profile_desc_anchor)
{
Gpi_Profile_Buffer_Entry *p = &(ticket->desc->buffer[ticket->index]);
Gpi_Profile_Buffer_Entry *p_end = &(ticket->desc->buffer[ticket->desc->buffer_length]);
for (; p < p_end; ++p)
{
if (0 != p->line)
{
*name = ticket->desc->name;
register int a, b;
register int ie = gpi_int_lock();
a = p->line;
b = p->timestamp;
gpi_int_unlock(ie);
*line = a;
*timestamp = 0x00ffffff - b;
ticket->index = ARRAY_INDEX(p, ticket->desc->buffer) + 1;
return 1;
}
}
ticket->desc = ticket->desc->next;
ticket->index = 0;
}
ticket->desc = 0;
return 0;
}
//**************************************************************************************************
//**************************************************************************************************
/***************************************************************************************************
***************************************************************************************************
*
* Copyright (c) 2019, Networked Embedded Systems Lab, TU Dresden
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the NES Lab or TU Dresden 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 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 THE COPYRIGHT HOLDER 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.
*
***********************************************************************************************//**
*
* @file gpi/arm/armv7-m/profile.h
*
* @brief support for program execution time profiling
*
* @version $Id$
* @date TODO
*
* @author Carsten Herrmann
*
***************************************************************************************************
@details
TODO
**************************************************************************************************/
#ifndef __GPI_ARMv7M_PROFILING_H__
#define __GPI_ARMv7M_PROFILING_H__
//**************************************************************************************************
//***** Includes ***********************************************************************************
#include "gpi/tools.h"
#include <stdint.h>
#include <string.h>
//**************************************************************************************************
//***** Global (Public) Defines and Consts *********************************************************
// use this macro once per file (on file scope, for each file with calls to GPI_PROFILE())
#define GPI_PROFILE_SETUP(_name_, _lines_, _granularity_) \
\
ASSERT_CT_STATIC(IS_POWER_OF_2(_granularity_), granularity_must_be_power_of_2); \
static const uint_fast8_t gpi_profile_shift = MSB(_granularity_); \
static Gpi_Profile_Buffer_Entry gpi_profile_buffer[(_lines_ + _granularity_ - 1) / _granularity_]; \
static Gpi_Profile_Desc gpi_profile_desc; \
\
static void __attribute__((constructor)) gpi_profile_setup() { \
gpi_profile_desc.prev = gpi_profile_desc_anchor.prev; \
gpi_profile_desc.next = &gpi_profile_desc_anchor; \
gpi_profile_desc.prev->next = &gpi_profile_desc; \
gpi_profile_desc.next->prev = &gpi_profile_desc; \
gpi_profile_desc.buffer = &gpi_profile_buffer[0]; \
gpi_profile_desc.buffer_length = NUM_ELEMENTS(gpi_profile_buffer); \
gpi_profile_desc.name = _name_; \
memset(gpi_profile_buffer, 0, sizeof(gpi_profile_buffer)); \
}
// record timestamp
#define GPI_PROFILE() \
do { \
ASSERT_CT((__LINE__ >> gpi_profile_shift) < NUM_ELEMENTS(gpi_profile_buffer), profile_buffer_overflow); \
register int t1, t2; \
__asm__ volatile ( \
"mov %0, #0xE000E000 \n" \
"ldr %1, =gpi_profile_buffer \n" \
"ldr %0, [%0, #0x18] \n" \
"str %0, [%1, %2] \n" \
"movw %0, " STRINGIFY(__LINE__) " \n" \
"str %0, [%1, %2 + 4] \n" \
: "=&r"(t1), "=&r"(t2) \
: "i"((__LINE__ >> gpi_profile_shift) << 3) \
/*: "memory"*/ \
); \
} while (0)
//**************************************************************************************************
//***** Local (Private) Defines and Consts *********************************************************
//**************************************************************************************************
//***** Forward Class and Struct Declarations ******************************************************
struct Gpi_Profile_Desc_;
//**************************************************************************************************
//***** Global Typedefs and Class Declarations *****************************************************
typedef struct Gpi_Profile_Buffer_Entry_
{
uint32_t timestamp;
uint16_t line;
uint16_t _unused;
} Gpi_Profile_Buffer_Entry;
//**************************************************************************************************
typedef struct Gpi_Profile_Desc_
{
struct Gpi_Profile_Desc_ *prev;
struct Gpi_Profile_Desc_ *next;
Gpi_Profile_Buffer_Entry *buffer;
uint32_t buffer_length;
const char *name;
} Gpi_Profile_Desc;
//**************************************************************************************************
typedef struct Gpi_Profile_Ticket_
{
Gpi_Profile_Desc *desc;
uint_fast32_t index;
} Gpi_Profile_Ticket;
//**************************************************************************************************