📄 dynamicloaderp.nc
字号:
/*
* Copyright (c) 2008 Johns Hopkins University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written
* agreement is hereby granted, provided that the above copyright
* notice, the (updated) modification history and the author appear in
* all copies of this source code.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
* @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
*/
#include SLCS_TYPES_FILE
#include "thread.h"
module DynamicLoaderP
{
provides {
interface Init;
interface DynamicLoader;
}
uses {
interface Leds;
interface BlockRead as ImageRead[uint8_t id];
interface DynamicThread;
interface ThreadNotification[uint8_t id];
interface ThreadScheduler;
interface ReferenceCounter;
interface PMManager;
#ifndef DISABLE_LOADER_USERBUTTON
interface UserButton;
#endif
}
}
implementation
{
uint8_t *code; // Points to first byte of the program code in the internal flash
uint8_t *tablesMemory;
void *gVarMemory;
struct prog_desc prog_desc;
init_block_t *proc;
uint16_t codePtr; // Records what code has been copied to the internal flash
uint16_t nextAddr;
uint8_t *nextTask_chain; // Used to update the next patching address in a chain
uint8_t readSource; // Loads from flash or memory
uint16_t readSourceOffset; // If loading from memory, then this is effectively the passed-in memory address
error_t retError = FAIL;
tosthread_t handler;
uint16_t threadCodeSizes[TOSTHREAD_MAX_NUM_THREADS];
uint16_t codeFirstAddrs[TOSTHREAD_MAX_NUM_THREADS];
async event void ThreadNotification.justCreated[uint8_t id]()
{
thread_t *t = call ThreadScheduler.threadInfo(id);
if(t->init_block != NULL) {
call ReferenceCounter.increment(&(t->init_block->thread_counter));
}
}
async event void ThreadNotification.aboutToDestroy[uint8_t id]()
{
thread_t *t = call ThreadScheduler.threadInfo(id);
if(t->init_block != NULL) {
call ReferenceCounter.decrement(&(t->init_block->thread_counter));
}
}
task void loadDoneTask()
{
if (retError != SUCCESS)
handler = TOSTHREAD_INVALID_THREAD_ID;
if (readSource == READSOURCE_MEMORY) {
signal DynamicLoader.loadFromMemoryDone(((void *)readSourceOffset), handler, retError);
} else {
signal DynamicLoader.loadFromFlashDone(readSource, handler, retError);
}
}
void initProgDesc()
{
prog_desc.main_addr = 0;
prog_desc.alloc_count = 0;
prog_desc.g_reloc_count = 0;
prog_desc.l_reloc_count = 0;
prog_desc.code_count = 0;
prog_desc.patch_table_count = 0;
prog_desc.loading_stage = 0;
codePtr = 0;
}
void errorHandler()
{
call Leds.set(7);
if (tablesMemory != NULL) { free(tablesMemory); tablesMemory = NULL; }
if (gVarMemory != NULL) { free(gVarMemory); gVarMemory = NULL; }
if (proc != NULL) { free(proc); proc = NULL; }
initProgDesc();
retError = FAIL;
post loadDoneTask();
}
void run_proc(void *arg)
{
init_block_t* curProc = arg;
thread_t* t = call ThreadScheduler.currentThreadInfo();
t->init_block = curProc;
(*(curProc->init_ptr))(curProc->init_arg);
call ReferenceCounter.waitOnValue(&(curProc->thread_counter), 0);
call PMManager.release(codeFirstAddrs[t->id], threadCodeSizes[t->id]);
codeFirstAddrs[t->id] = 0;
threadCodeSizes[t->id] = 0;
if (curProc->globals != NULL) {
free(curProc->globals);
}
free(curProc);
}
task void start_prog()
{
free(tablesMemory);
proc = malloc(sizeof(init_block_t));
proc->globals = gVarMemory;
proc->init_ptr = (void *)((uint16_t)code + prog_desc.main_addr);
proc->init_arg = NULL;
call ReferenceCounter.init( &(proc->thread_counter) );
if (call DynamicThread.create(&handler, run_proc, proc, 200) == SUCCESS) {
codeFirstAddrs[handler] = (uint16_t)code;
threadCodeSizes[handler] = prog_desc.code_count;
retError = SUCCESS;
post loadDoneTask();
} else {
retError = FAIL;
post loadDoneTask();
if (proc->globals != NULL) {
free(proc->globals);
}
free(proc);
}
initProgDesc();
}
// Gets write access to the internal flash
void eeprom_w()
{
FCTL2 = FWKEY + FSSEL1 + FN2; // selects SMCLK and divides it by 4
FCTL3 = FWKEY; // enables the writing/erasing by clearing the LOCK bit
FCTL1 = FWKEY + WRT; // enables the writing
}
// Gets read-only access to the internal flash
void eeprom_r()
{
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK; // disabling the writing/erasing
}
// Calculates where should the code be placed in the internal flash
/*
uint16_t eeprom_code_addr()
{
uint16_t addr;
addr = (((prog_desc.code_count - 1) / 512) + 1) * 512; // Spaces needed for the code
addr = 0xFFFF - 512 - addr + 1; // The 1 is to align the code
return addr;
}
*/
// Loads program image meta data
void loader_metaData()
{
prog_desc.patch_table_count = prog_desc.alloc_count +
prog_desc.g_reloc_count +
prog_desc.l_reloc_count;
prog_desc.code_offset = sizeof(prog_desc.main_addr) +
sizeof(prog_desc.alloc_count) +
sizeof(prog_desc.alloc_size) +
sizeof(prog_desc.g_reloc_count) +
sizeof(prog_desc.l_reloc_count) +
sizeof(prog_desc.datasec_count) +
sizeof(prog_desc.code_count) +
(prog_desc.patch_table_count * 4) +
(prog_desc.datasec_count * 6);
if (prog_desc.patch_table_count > 0 || prog_desc.datasec_count > 0) {
if ((prog_desc.patch_table_count * 4) > (prog_desc.datasec_count * 6)) {
tablesMemory = malloc(prog_desc.patch_table_count * 4);
} else {
tablesMemory = malloc(prog_desc.datasec_count * 6);
}
} else {
tablesMemory = NULL;
}
}
// Prepares the patch table before patching addresses in the binary code
void loader_patch_table()
{
uint16_t i, tempUInt16 = 0;
// Find out the total space global variables need, and malloc
/*
for (i = 0; i < (prog_desc.alloc_count * 4); i+=4) {
tempUInt16 += *((uint16_t *)&tablesMemory[i]);
*((uint16_t *)&tablesMemory[i]) = tempUInt16 - *((uint16_t *)&tablesMemory[i]);
}
*/
if (prog_desc.alloc_size > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -