2 # This file is Copyright 2006, 2007, 2009, 2010 Dean Hall.
4 # This file is part of the PyMite VM.
5 # The PyMite VM is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
8 # The PyMite VM is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
12 # is seen in the file COPYING in this directory.
17 #define __FILE_ID__ 0x15
22 * \brief PyMite User API
24 * High-level functions to initialize and run PyMite
31 /** Number of millisecond-ticks to pass before scheduler is run */
32 #define PM_THREAD_TIMESLICE_MS 10
35 /** Stores the timer millisecond-ticks since system start */
36 volatile uint32_t pm_timerMsTicks
= 0;
38 /** Stores tick timestamp of last scheduler run */
39 volatile uint32_t pm_lastRescheduleTimestamp
= 0;
43 pm_init(PmMemSpace_t memspace
, uint8_t const * const pusrimg
)
47 /* Initialize the hardware platform */
49 PM_RETURN_IF_ERROR(retval
);
51 /* Initialize the heap and the globals */
53 PM_RETURN_IF_ERROR(retval
);
55 retval
= global_init();
56 PM_RETURN_IF_ERROR(retval
);
58 /* Load usr image info if given */
59 if (pusrimg
!= C_NULL
)
61 retval
= img_appendToPath(memspace
, pusrimg
);
69 pm_run(uint8_t const *modstr
)
74 uint8_t const *pmodstr
= modstr
;
76 /* Import module from global struct */
77 retval
= string_new(&pmodstr
, &pstring
);
78 PM_RETURN_IF_ERROR(retval
);
79 retval
= mod_import(pstring
, &pmod
);
80 PM_RETURN_IF_ERROR(retval
);
82 /* Load builtins into thread */
83 retval
= global_setBuiltins((pPmFunc_t
)pmod
);
84 PM_RETURN_IF_ERROR(retval
);
86 /* Interpret the module's bcode */
87 retval
= interp_addThread((pPmFunc_t
)pmod
);
88 PM_RETURN_IF_ERROR(retval
);
89 retval
= interpret(INTERP_RETURN_ON_NO_THREADS
);
92 * De-initialize the hardware platform.
93 * Ignore plat_deinit's retval so interpret's retval returns to caller.
101 /* Warning: Can be called in interrupt context! */
103 pm_vmPeriodic(uint16_t usecsSinceLastCall
)
106 * Add the full milliseconds to pm_timerMsTicks and store additional
107 * microseconds for the next run. Thus, usecsSinceLastCall must be
108 * less than 2^16-1000 so it will not overflow usecResidual.
110 static uint16_t usecResidual
= 0;
112 C_ASSERT(usecsSinceLastCall
< 64536);
114 usecResidual
+= usecsSinceLastCall
;
115 while (usecResidual
>= 1000)
117 usecResidual
-= 1000;
121 /* Check if enough time has passed for a scheduler run */
122 if ((pm_timerMsTicks
- pm_lastRescheduleTimestamp
)
123 >= PM_THREAD_TIMESLICE_MS
)
125 interp_setRescheduleFlag((uint8_t)1);
126 pm_lastRescheduleTimestamp
= pm_timerMsTicks
;