python-on-a-chip online compiler

Dependencies:   mbed TSI

/media/uploads/va009039/p14p-f446re.png

more info: python-on-a-chip

vm/pm.c

Committer:
va009039
Date:
2016-04-14
Revision:
15:94ca5c8003e5
Parent:
0:65f1469d6bfb

File content as of revision 15:94ca5c8003e5:

/*
# This file is Copyright 2006 Dean Hall.
# This file is part of the PyMite VM.
# This file is licensed under the MIT License.
# See the LICENSE file for details.
*/


#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(uint8_t *heap_base, uint32_t heap_size,
        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(heap_base, heap_size);
    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;
    uint8_t objid1;
    uint8_t objid2;

    /* Import module from global struct */
    retval = string_new(&pmodstr, &pstring);
    PM_RETURN_IF_ERROR(retval);
    heap_gcPushTempRoot(pstring, &objid1);
    retval = mod_import(pstring, &pmod);
    PM_RETURN_IF_ERROR(retval);

    /* Load builtins into thread */
    heap_gcPushTempRoot(pmod, &objid2);
    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);
    heap_gcPopTempRoot(objid1);
    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;
}