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

📄 flashutils.c

📁 用IAR开发的ZIGBEE网络路由例子
💻 C
📖 第 1 页 / 共 2 页
字号:
}

STATIC  uint32 CRC32Value(uint16 inCRC)
{
    int16  j;
    uint32 ulCRC = inCRC;

    // for this byte (inCRC)...
    for (j=8; j; j--) {
        // lsb on? yes -- shift right and XOR with poly. else just shift
        if (ulCRC & 1) {
            ulCRC = (ulCRC >> 1) ^ CRC32_POLYNOMIAL;
        }
        else  {
            ulCRC >>= 1;
        }
    }

    return ulCRC;
}

/************************************************************************************
 *   uint8 GetPreamble
 *      Purpose: get image preamble
 *
 *        This routine is avaliable to application code. It is re-entrant but not
 *        thread-safe.
 *
 *      Arguments:
 *        input:
 *          baseAddr: base address of image
 *        output:
 *          info: void pointer to destination memory
 *      Returns:
 *        0: OK
 *        1: error
 *
 *   NOTE: this works only because the preamble is always on the first flash page.
 *         This is important given that the downloaded image can wrap. It won't wrap
 *         within a page.
 ************************************************************************************/
STATIC uint8 GetPreamble(image_t itype, uint32 baseAddr, preamble_t *info)
{
    uint8 preOffset;

    if (IMAGE_DL == itype)  {

        mbox.AccessZLOADStatus(ACTION_GET, SFIELD_PREAMBLE_OFFSET, &preOffset);
        baseAddr += preOffset;
        rw_Xmem(XMEM_READ, baseAddr, (uint8 *)info, sizeof(preamble_t));
    }
    else if (IMAGE_ACTIVE == itype) {
        uint8 i;

        baseAddr += PREAMBLE_BASE;

        // need > 16-bit pointer arithmetic
        for (i=0; i<sizeof(preamble_t); ++i, ++baseAddr)  {
            *((uint8 *)info+i) = GetCodeByte(baseAddr);
        }
    }
    else  {
      return 1;
    }

    return 0;
}


/************************************************************************************
 *   uint8 AccessStatus
 *      Purpose: get and set fields in OAD persistent memory
 *
 *        This routine is avaliable to application code. It neither re-entrant nor
 *        thread-safe.
 *
 *      Arguments:
 *        input:
 *          action: get or set
 *          sfield: which field to operate on
 *        output:
 *          info: void pointer to source (set) or destination (get) memory
 *      Returns:
 *        0: OK
 *        1: bad action or field
 ************************************************************************************/
STATIC  uint8 AccessStatus(action_t action, sfield_t sfield, void *info)
{
    uint8   bcnt, os, rc = 0;

    // all results for this function (except the boot sector size) are byte copies
    // the offset and byte counts are set based on boot code knowledge of how the
    // persistent memory is arranged. the offsets and sizes are set here. they are
    // defined in a header. they could be calculated but it takes a lot more code.
    switch (sfield)  {
#if 0   // base and first page always the same for the 8051 with external memory
        case SFIELD_DLFIRSTPAGE_ADDR:
            bcnt = sizeof(uint32);
            os   = OADPM_OS_FIRSTPAGE_ADDR;
            break;
#else
        case SFIELD_DLFIRSTPAGE_ADDR:
#endif
        case SFIELD_DLBASE:
            bcnt = sizeof(uint32);
            os   = OADPM_OS_BADDR;
            break;

        case SFIELD_PREAMBLE_OFFSET:
            bcnt = sizeof(uint8);
            os   = OADPM_OS_PREAMBLE_OFFSET;
            break;

            // we don't need to support the next few accesses now. they were intended
            // to support the case where the entire image could not be downloaded and
            // we needed to have server context in case of failure. they have been
            // tested but are removed for now.
#if 0
        case SFIELD_SERVER_IEEE_ADDR:
            bcnt = SIZEOF_IEEE_ADDRESS;
            os   = OADPM_OS_IEEE_ADDR;
            break;

        case SFIELD_SERVER_NWK_ADDR:
            bcnt = sizeof(uint16);
            os   = OADPM_OS_NWK_ADDR;
            break;

        case SFIELD_SERVER_ENDPOINT:
            bcnt = sizeof(uint8);
            os   = OADPM_OS_ENDPT;
            break;

        case SFIELD_IMAGE_ID:
            bcnt = SIZEOF_DLIMAGE_INFO;
            os   = OADPM_OS_DLIMG_INFO;
            break;
#endif
        case SFIELD_STATUS:
            bcnt = sizeof(uint16);
            os   = OADPM_OS_STATUS;
            break;

#if 0  // not used for CC2430
        case SFIELD_BOOTSIZE:
            // doesn't really belong here because it isn't kept in PM but
            // it is conventient to support it with this API
            if (action == ACTION_SET)  {
                // not legal
                return 1;
            }
            *(uint16 *)info = bootSize;
            return 0;
#endif
        case SFIELD_EXTERNAL_MEM_OS:
            // doesn't really belong here because it isn't kept in PM but
            // it is conventient to support it with this API
            if (action == ACTION_SET)  {
                // not legal
                return 1;
            }
            *(uint16 *)info = DL_BASE_ADDRESS;
            return 0;

        default:
            rc = 1;
            break;
    }

    if (!rc)  {
        if (action == ACTION_SET)  {
          rw_Xmem(XMEM_WRITE, SYSNV_BASE_ADDRESS + os, info, bcnt);
        }
        else if (action == ACTION_GET)  {
          rw_Xmem(XMEM_READ, SYSNV_BASE_ADDRESS + os, info, bcnt);
        }
        else  {
            rc = 1;
        }
    }

    return rc;
}

STATIC  uint8 ReadFlash(image_t itype, uint32 address, uint8 __xdata *buf, uint16 len)
{
  uint8 rc = 0;

  if (IMAGE_ACTIVE == itype)  {
    uint16 i = len;

    while (i--)  {
      *buf++ = GetCodeByte(address++);
    }
  }
  else if (IMAGE_DL == itype)  {
    rw_Xmem(XMEM_READ, address, buf, len);
  }
  else  {
    rc = 1;
  }

  return rc;
}

STATIC  uint8 WriteFlash(image_t itype, uint32 address, uint8 __xdata *buf, uint16 len)
{
  uint8 rc = 1;  // 1 == write was OK.

  if (IMAGE_ACTIVE == itype)  {
    uint16  fbase, i;
    uint8   page = address >> CHIP_SHIFTCOUNT;

    // if we're on a page boundary for the target (chip) flash, erase the page
    // this implies that we either write a page sequentially or minimally
    // write the first address on the first call so the page gets eraseed.
    if (!(address & 0x000007FF))  {
      FLASH_ERASE_PAGE(page);
    }


    // OK. do the rest. use DMA Channel 0
    // Set up Flash DMA

    FlashDMA.DST_HI  = 0xdf;
    FlashDMA.DST_LO  = 0xaf;
    FlashDMA.VLEN    = 0x00;
    FlashDMA.LEN     = 0x04;
    FlashDMA.TRIG    = 0x12;
    FlashDMA.INCMODE = 0x42;

    DMA0CFGH = (uint16)&FlashDMA >> 8;
    DMA0CFGL = (uint16)&FlashDMA;

    fbase = (page << 9) + ((address & 0x000007FF)>>2);

    // 'len' must be 0 (mod 4)
    for (i=0; i<(len/4); ++i)  {
      // set buffer pointer in DMA config info
      FlashDMA.SRC_HI  = (uint16)buf >> 8;
      FlashDMA.SRC_LO  = (uint16)buf;
      // Set Flash write address based on fbase
      FADDRH = fbase >> 8;
      FADDRL = fbase;

      DMAARM = 0x01;
      halFlashDmaTrigger();
      while (!(DMAIRQ & 0x01));   // wait for DMA transfer
      while ( FCTL & FWBUSY );  // wait until Flash controller not busy
      DMAIRQ &= ~0x01;
      fbase++;
      buf += 4;
    }
  }
  else if (IMAGE_DL == itype)  {
    rw_Xmem(XMEM_WRITE, address, buf, len);
  }
  else  {
    rc = 0;
  }

  return rc;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -