⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynamicloaderp.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -