mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-30 08:24:11 +01:00
130 lines
3.1 KiB
C
130 lines
3.1 KiB
C
|
/*
|
||
|
# This file is Copyright 2006, 2007, 2009, 2010 Dean Hall.
|
||
|
#
|
||
|
# This file is part of the PyMite VM.
|
||
|
# The PyMite VM is free software: you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
|
||
|
#
|
||
|
# The PyMite VM is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
# A copy of the GNU GENERAL PUBLIC LICENSE Version 2
|
||
|
# is seen in the file COPYING in this directory.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#undef __FILE_ID__
|
||
|
#define __FILE_ID__ 0x15
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \file
|
||
|
* \brief PyMite User API
|
||
|
*
|
||
|
* High-level functions to initialize and run PyMite
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "pm.h"
|
||
|
|
||
|
|
||
|
/** Number of millisecond-ticks to pass before scheduler is run */
|
||
|
#define PM_THREAD_TIMESLICE_MS 10
|
||
|
|
||
|
|
||
|
/** Stores the timer millisecond-ticks since system start */
|
||
|
volatile uint32_t pm_timerMsTicks = 0;
|
||
|
|
||
|
/** Stores tick timestamp of last scheduler run */
|
||
|
volatile uint32_t pm_lastRescheduleTimestamp = 0;
|
||
|
|
||
|
|
||
|
PmReturn_t
|
||
|
pm_init(PmMemSpace_t memspace, uint8_t const * const pusrimg)
|
||
|
{
|
||
|
PmReturn_t retval;
|
||
|
|
||
|
/* Initialize the hardware platform */
|
||
|
retval = plat_init();
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
|
||
|
/* Initialize the heap and the globals */
|
||
|
retval = heap_init();
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
|
||
|
retval = global_init();
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
|
||
|
/* Load usr image info if given */
|
||
|
if (pusrimg != C_NULL)
|
||
|
{
|
||
|
retval = img_appendToPath(memspace, pusrimg);
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
PmReturn_t
|
||
|
pm_run(uint8_t const *modstr)
|
||
|
{
|
||
|
PmReturn_t retval;
|
||
|
pPmObj_t pmod;
|
||
|
pPmObj_t pstring;
|
||
|
uint8_t const *pmodstr = modstr;
|
||
|
|
||
|
/* Import module from global struct */
|
||
|
retval = string_new(&pmodstr, &pstring);
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
retval = mod_import(pstring, &pmod);
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
|
||
|
/* Load builtins into thread */
|
||
|
retval = global_setBuiltins((pPmFunc_t)pmod);
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
|
||
|
/* Interpret the module's bcode */
|
||
|
retval = interp_addThread((pPmFunc_t)pmod);
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
retval = interpret(INTERP_RETURN_ON_NO_THREADS);
|
||
|
|
||
|
/*
|
||
|
* De-initialize the hardware platform.
|
||
|
* Ignore plat_deinit's retval so interpret's retval returns to caller.
|
||
|
*/
|
||
|
plat_deinit();
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Warning: Can be called in interrupt context! */
|
||
|
PmReturn_t
|
||
|
pm_vmPeriodic(uint16_t usecsSinceLastCall)
|
||
|
{
|
||
|
/*
|
||
|
* Add the full milliseconds to pm_timerMsTicks and store additional
|
||
|
* microseconds for the next run. Thus, usecsSinceLastCall must be
|
||
|
* less than 2^16-1000 so it will not overflow usecResidual.
|
||
|
*/
|
||
|
static uint16_t usecResidual = 0;
|
||
|
|
||
|
C_ASSERT(usecsSinceLastCall < 64536);
|
||
|
|
||
|
usecResidual += usecsSinceLastCall;
|
||
|
while (usecResidual >= 1000)
|
||
|
{
|
||
|
usecResidual -= 1000;
|
||
|
pm_timerMsTicks++;
|
||
|
}
|
||
|
|
||
|
/* Check if enough time has passed for a scheduler run */
|
||
|
if ((pm_timerMsTicks - pm_lastRescheduleTimestamp)
|
||
|
>= PM_THREAD_TIMESLICE_MS)
|
||
|
{
|
||
|
interp_setRescheduleFlag((uint8_t)1);
|
||
|
pm_lastRescheduleTimestamp = pm_timerMsTicks;
|
||
|
}
|
||
|
return PM_RET_OK;
|
||
|
}
|