Skip to content

Instantly share code, notes, and snippets.

@stephanemainchain
Created March 27, 2019 16:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephanemainchain/8f9ad6ae4ed2ee2287b4244b548bfecb to your computer and use it in GitHub Desktop.
Save stephanemainchain/8f9ad6ae4ed2ee2287b4244b548bfecb to your computer and use it in GitHub Desktop.
/*
* Copyright 2016-2017 IS2T. All rights reserved.
* For demonstration purpose only.
* IS2T PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
/* Includes ------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include "cmsis_os.h"
#include "microej.h"
#include "LLMJVM_impl.h"
#include "native_time.h"
#include "us_ticker_api.h"
#include <inttypes.h>
/* Private function header ---------------------------------------------------*/
static void wake_up_timer_callback(void const* timerId);
/* Defines -------------------------------------------------------------------*/
/*
* Useful macros and definitions
*/
// ID for the Wake Up Timer
#define WAKE_UP_TIMER_ID 42
/* Globals -------------------------------------------------------------------*/
// Application time offset
static int64_t LLMJVM_MBED_application_time_offset = 0;
//Absolute time in ticks at which timer will be launched
static int64_t LLMJVM_MBED_next_wake_up_time = INT64_MAX;
// Binary Semaphore to wakeup microJVM
static osSemaphoreId LLMJVM_MBED_Semaphore;
static osSemaphoreDef(LLMJVM_MBED_Semaphore);
// Wake up timer
osTimerId LLMJVM_MBED_wake_up_timer;
static osTimerDef(LLMJVM_MBED_wake_up_timer, wake_up_timer_callback);
/* Private functions ---------------------------------------------------------*/
// Since LLMJVM_schedule() prototype does not match the timer callback prototype,
// we create a wrapper around it and check the ID of the timer.
static void wake_up_timer_callback(void const* timerId)
{
if((uint32_t)timerId == WAKE_UP_TIMER_ID)
{
osTimerStop(LLMJVM_MBED_wake_up_timer);
LLMJVM_schedule();
}
}
/* Public functions ----------------------------------------------------------*/
/*
* Implementation of functions from LLMJVM_impl.h
* and other helping functions.
*/
// Creates the timer used to callback the LLMJVM_schedule() function.
// After its creation, the timer is idle.
int32_t LLMJVM_IMPL_initialize()
{
// Create a timer to scheduler alarm for the VM
LLMJVM_MBED_wake_up_timer = osTimerCreate(osTimer(LLMJVM_MBED_wake_up_timer), osTimerOnce, (void*)(WAKE_UP_TIMER_ID));
if(LLMJVM_MBED_wake_up_timer == NULL)
{
printf("ERROR : osTimerCreate\r\n");
return LLMJVM_ERROR;
}
LLMJVM_MBED_Semaphore = osSemaphoreCreate(osSemaphore(LLMJVM_MBED_Semaphore), 0);
if(LLMJVM_MBED_Semaphore == NULL)
{
printf("ERROR : osSemaphoreCreate\r\n");
return LLMJVM_ERROR;
}
/* Get Time timer initialize */
us_ticker_init();
return LLMJVM_OK;
}
// Once the task is started, save a handle to it.
int32_t LLMJVM_IMPL_vmTaskStarted()
{
return LLMJVM_OK;
}
// Schedules requests from the VM
int32_t LLMJVM_IMPL_scheduleRequest(int64_t absoluteTime)
{
int32_t relativeTime;
//First check if absolute time is lower than current schedule time
if(absoluteTime < LLMJVM_MBED_next_wake_up_time)
{
// Save new alarm absolute time
LLMJVM_MBED_next_wake_up_time = absoluteTime;
// Stop current timer (no delay)
osTimerStop(LLMJVM_MBED_wake_up_timer);
// Determine relative time/tick
relativeTime = (int32_t)(absoluteTime - LLMJVM_IMPL_getCurrentTime(MICROEJ_TRUE));
if(relativeTime > 0)
{
// Schedule the new alarm
osTimerStart(LLMJVM_MBED_wake_up_timer, (uint32_t)relativeTime);
if(LLMJVM_MBED_wake_up_timer != 0)
{
return LLMJVM_ERROR;
}
else
{
return LLMJVM_OK;
}
}
else
{
// 'absoluteTime' has been reached already, notify the VM now
return LLMJVM_schedule();
}
}
// else : nothing to do. An sooner alarm is scheduled.
return LLMJVM_OK;
}
// Suspends the VM task if the pending flag is not set
int32_t LLMJVM_IMPL_idleVM()
{
int32_t token = osSemaphoreWait(LLMJVM_MBED_Semaphore, osWaitForever);
return (token == -1) ? LLMJVM_ERROR : LLMJVM_OK;
}
// Wakes up the VM task and reset next wake up time
int32_t LLMJVM_IMPL_wakeupVM()
{
osStatus res;
res = osSemaphoreRelease(LLMJVM_MBED_Semaphore);
LLMJVM_MBED_next_wake_up_time = INT64_MAX;
return (res == osOK) ? LLMJVM_OK : LLMJVM_ERROR;
}
// Clear the pending wake up flag
int32_t LLMJVM_IMPL_ackWakeup()
{
/* Make sure no token are available in wake up semaphore */
int32_t token = 0;
do {
token = osSemaphoreWait(LLMJVM_MBED_Semaphore, 0);
}
while (token > 0);
return (token == 0) ? LLMJVM_OK : LLMJVM_ERROR;
}
int32_t LLMJVM_IMPL_getCurrentTaskID()
{
return (int32_t) osThreadGetId();
}
void LLMJVM_native_setTime(int64_t t)
{
int64_t currentTime = LLMJVM_IMPL_getCurrentTime(MICROEJ_TRUE);
LLMJVM_MBED_application_time_offset = t - currentTime;
}
// Sets application time
void LLMJVM_IMPL_setApplicationTime(int64_t t)
{
LLMJVM_native_setTime(t);
}
int64_t LLMJVM_native_getTime(uint8_t system)
{
int64_t systemTime = us_ticker_read64()/1000;
return system ? systemTime : systemTime + LLMJVM_MBED_application_time_offset;
}
// Gets the system or the application time in milliseconds
int64_t LLMJVM_IMPL_getCurrentTime(uint8_t system)
{
return LLMJVM_native_getTime(system);
}
// Gets the current system time in nanoseconds
int64_t LLMJVM_IMPL_getTimeNanos()
{
return us_ticker_read64()*1000;
}
int32_t LLMJVM_IMPL_shutdown(void)
{
// nothing to do
return LLMJVM_OK;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment