Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add target_hash_serial_number() #119

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion inc/core/CodalHeapAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ struct HeapDefinition
PROCESSOR_WORD_TYPE *heap_start; // Physical address of the start of this heap.
PROCESSOR_WORD_TYPE *heap_end; // Physical address of the end of this heap.
};
extern PROCESSOR_WORD_TYPE codal_heap_start;

/**
* Create and initialise a given memory region as for heap storage.
Expand Down
6 changes: 6 additions & 0 deletions inc/core/codal_target_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ extern "C"

void target_disable_irq();

int target_get_irq_disabled();

void target_reset();

void target_wait(uint32_t milliseconds);
Expand All @@ -44,6 +46,10 @@ extern "C"
int target_random(int max);

uint64_t target_get_serial();

PROCESSOR_WORD_TYPE target_heap_start();

unsigned target_get_serial_buffer(void *serial, unsigned maxbytes);

void target_wait_for_event();

Expand Down
4 changes: 2 additions & 2 deletions source/core/CodalHeapAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,10 @@ void* device_malloc (size_t size)
heap_count = 0;

#if CONFIG_ENABLED(CODAL_LOW_LEVEL_VALIDATION)
if(device_create_heap((PROCESSOR_WORD_TYPE)(codal_heap_start), (PROCESSOR_WORD_TYPE)(DEVICE_STACK_BASE) - (PROCESSOR_WORD_TYPE)(DEVICE_STACK_SIZE)) == DEVICE_INVALID_PARAMETER)
if(device_create_heap(target_heap_start(), (PROCESSOR_WORD_TYPE)(DEVICE_STACK_BASE) - (PROCESSOR_WORD_TYPE)(DEVICE_STACK_SIZE)) == DEVICE_INVALID_PARAMETER)
target_panic(DEVICE_HEAP_ERROR);
#else
device_create_heap((PROCESSOR_WORD_TYPE)(codal_heap_start), (PROCESSOR_WORD_TYPE)(DEVICE_STACK_BASE) - (PROCESSOR_WORD_TYPE)(DEVICE_STACK_SIZE));
device_create_heap(target_heap_start(), (PROCESSOR_WORD_TYPE)(DEVICE_STACK_BASE) - (PROCESSOR_WORD_TYPE)(DEVICE_STACK_SIZE));
#endif
initialised = 1;
}
Expand Down
62 changes: 56 additions & 6 deletions source/core/codal_default_target_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,29 @@
#include "CodalCompat.h"
#include "Timer.h"

__attribute__((weak)) void target_wait(uint32_t milliseconds)
#define WEAK __attribute__((weak))

WEAK void target_wait(uint32_t milliseconds)
{
codal::system_timer_wait_ms(milliseconds);
}

__attribute__((weak)) void target_wait_us(uint32_t us)
WEAK void target_wait_us(uint32_t us)
{
codal::system_timer_wait_us(us);
}

__attribute__((weak)) int target_seed_random(uint32_t rand)
WEAK int target_seed_random(uint32_t rand)
{
return codal::seed_random(rand);
}

__attribute__((weak)) int target_random(int max)
WEAK int target_random(int max)
{
return codal::random(max);
}

__attribute__((weak)) void target_panic(int statusCode)
WEAK void target_panic(int statusCode)
{
target_disable_irq();

Expand All @@ -33,8 +35,56 @@ __attribute__((weak)) void target_panic(int statusCode)
}
}

__attribute__((weak)) void target_deepsleep()
WEAK void target_deepsleep()
{
// if not implemented, default to WFI
target_wait_for_event();
}

static uint32_t murmur_hash2_core(const uint32_t *d, int words)
{
const uint32_t m = 0x5bd1e995;
uint32_t h = 0;

while (words--)
{
uint32_t k = *d++;
k *= m;
k ^= k >> 24;
k *= m;
h *= m;
h ^= k;
}

return h;
}

// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
static uint32_t hash_fnv1a(const void *data, unsigned len)
{
const uint8_t *d = (const uint8_t *)data;
uint32_t h = 0x811c9dc5;
while (len--)
h = (h ^ *d++) * 0x1000193;
return h;
}

/**
* Compute 64-bit hash of manufacturer provided serial number.
*/
WEAK uint64_t target_get_serial()
{
static uint64_t cache;
if (!cache)
{
uint32_t serialdata[8];
unsigned numbytes = target_get_serial_buffer(serialdata, sizeof(serialdata));
if (numbytes > sizeof(serialdata))
target_panic(DEVICE_HARDWARE_CONFIGURATION_ERROR);
uint32_t w1 = hash_fnv1a(serialdata, numbytes);
uint32_t w0 = murmur_hash2_core(serialdata, numbytes >> 2);
w0 &= ~0x02000000; // clear "universal" bit
cache = ((uint64_t)w0 << 32 | w1);
}
return cache;
}
138 changes: 138 additions & 0 deletions source/core/codal_default_target_hal_arm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include "codal_target_hal.h"
#include "CodalDmesg.h"
#include "CodalCompat.h"

#ifdef __arm__

#define WEAK __attribute__((weak))

static int8_t irq_disabled;
WEAK void target_enable_irq()
{
irq_disabled--;
if (irq_disabled <= 0)
{
irq_disabled = 0;
asm volatile("cpsie i" : : : "memory");
}
}

WEAK void target_disable_irq()
{
// always disable just in case - it's just one instruction
asm volatile("cpsid i" : : : "memory");
irq_disabled++;
}

WEAK int target_get_irq_disabled()
{
uint32_t result;
asm volatile("MRS %0, primask" : "=r"(result));
return result != 0;
}

WEAK void target_wait_for_event()
{
asm volatile("wfe");
}

/**
* Thread Context for an ARM Cortex-M cores.
*
* This is probably overkill, but the ARMCC compiler uses a lot register optimisation
* in its calling conventions, so better safe than sorry!
*/
struct PROCESSOR_TCB
{
uint32_t R0;
uint32_t R1;
uint32_t R2;
uint32_t R3;
uint32_t R4;
uint32_t R5;
uint32_t R6;
uint32_t R7;
uint32_t R8;
uint32_t R9;
uint32_t R10;
uint32_t R11;
uint32_t R12;
uint32_t SP;
uint32_t LR;
uint32_t stack_base;
};

WEAK PROCESSOR_WORD_TYPE fiber_initial_stack_base()
{
return DEVICE_STACK_BASE;
}

WEAK void *tcb_allocate()
{
return (void *)malloc(sizeof(PROCESSOR_TCB));
}

/**
* Configures the link register of the given tcb to have the value function.
*
* @param tcb The tcb to modify
* @param function the function the link register should point to.
*/
WEAK void tcb_configure_lr(void *tcb, PROCESSOR_WORD_TYPE function)
{
PROCESSOR_TCB *tcbPointer = (PROCESSOR_TCB *)tcb;
tcbPointer->LR = function;
}

/**
* Configures the link register of the given tcb to have the value function.
*
* @param tcb The tcb to modify
* @param function the function the link register should point to.
*/
WEAK void tcb_configure_sp(void *tcb, PROCESSOR_WORD_TYPE sp)
{
PROCESSOR_TCB *tcbPointer = (PROCESSOR_TCB *)tcb;
tcbPointer->SP = sp;
}

WEAK void tcb_configure_stack_base(void *tcb, PROCESSOR_WORD_TYPE stack_base)
{
PROCESSOR_TCB *tcbPointer = (PROCESSOR_TCB *)tcb;
tcbPointer->stack_base = stack_base;
}

WEAK PROCESSOR_WORD_TYPE tcb_get_stack_base(void *tcb)
{
PROCESSOR_TCB *tcbPointer = (PROCESSOR_TCB *)tcb;
return tcbPointer->stack_base;
}

WEAK PROCESSOR_WORD_TYPE get_current_sp()
{
register uint32_t result;
asm volatile("MRS %0, msp" : "=r"(result));
return (result);
}

WEAK PROCESSOR_WORD_TYPE tcb_get_sp(void *tcb)
{
PROCESSOR_TCB *tcbPointer = (PROCESSOR_TCB *)tcb;
return tcbPointer->SP;
}

WEAK void tcb_configure_args(void *tcb, PROCESSOR_WORD_TYPE ep, PROCESSOR_WORD_TYPE cp,
PROCESSOR_WORD_TYPE pm)
{
PROCESSOR_TCB *tcbPointer = (PROCESSOR_TCB *)tcb;
tcbPointer->R0 = (uint32_t)ep;
tcbPointer->R1 = (uint32_t)cp;
tcbPointer->R2 = (uint32_t)pm;
}

extern PROCESSOR_WORD_TYPE __end__;
WEAK PROCESSOR_WORD_TYPE target_heap_start()
{
return (PROCESSOR_WORD_TYPE)(&__end__);
}
#endif