示例#1
0
PUBLIC MEMD_ERR_T memd_FlashErase(UINT8 *startFlashAddress, UINT8 *endFlashAddress)
{
    UINT32 status;
    VOLATILE UINT16 * ptr;
    VOLATILE UINT16 *BankAddr;
    UINT32 phy_Start;
    UINT32 phy_End;
    UINT32 phys_end_add;
    UINT32 phys_start_add;
    MEMD_ERR_T errorcode=MEMD_ERR_NO;
    BOOL isLocked;
    UINT16 rdstatus;
//hal_HstSendEvent(0x5555);

    phys_start_add = (UINT32)startFlashAddress;

    MEMD_ASSERT((phys_start_add & 0xe0000000) == 0, 
        "flash_address is expected to be a byte offset within the flash chip, not an absolute address");
    // Check that start & end addresses are aligned
    if (endFlashAddress == NULL)
    {
        memd_FlashGetSectorLimits(phys_start_add, &phy_Start, &phy_End);
        phys_end_add = phy_End;
    } else
    {
        phys_end_add = (UINT32)endFlashAddress;
        MEMD_ASSERT((phys_end_add & 0xe0000000) == 0, 
            "flash_address is expected to be a byte offset within the flash chip, not an absolute address")
        if (phys_end_add != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(phys_end_add , &phy_Start, &phy_End);
            if (phys_end_add != phy_Start)
            {
                return MEMD_ERR_ALIGN;
            }
        }
    }

    memd_FlashGetSectorLimits(phys_start_add, &phy_Start, &phy_End);
    if (phys_start_add != phy_Start)
    {
        return MEMD_ERR_ALIGN;
    }

    hal_EbcFlashWriteEnable(TRUE);

    BankAddr = NULL;
    while (phy_Start != phys_end_add)
    {
        BankAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phy_Start&FLASHBANK_MASK));
        // phy_Start should already be aligned to sector boundary, so shouldn't need any more masking
        ptr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + phy_Start);

       
        memd_FlashGetLockStatus((UINT8*)((UINT32)ptr & MY_MASK),&isLocked);
	 // Re-enable EBC write
        hal_EbcFlashWriteEnable(TRUE);


        if(isLocked == TRUE)
        {
           memd_BlockLock((UINT8*)((UINT32)ptr & MY_MASK),NULL,FALSE);
           	 // while(1){;};
        }
  
        status = hal_SysEnterCriticalSection();		
        // Sector Erase command
        *(BankAddr) = CMD_BLOCK_ERASE_1;
        *(ptr) = CMD_BLOCK_ERASE_2;
        hal_SysExitCriticalSection(status);


        // pooling
        // Wait for Ready, then check status
        do{
             rdstatus = *BankAddr;
        }while((rdstatus & SR7) != SR7);   // Any address in the bank may be used

        // Should probably fix this scheme for reporting errors more cleanly.
        // For now, just prioritize the errors with the most significant error returned
        // in errorcode (order this list from least to most significant)
        if ((rdstatus & SR3) != 0)
        {
          	  while(1){;};
            // Vpp Invalid Error
            errorcode=MEMD_ERR_ERASE;
        }
        else if (((rdstatus & SR5) != 0) && ((rdstatus & SR4) != 0))
        {
            // Command Sequence Error
            errorcode=MEMD_ERR_ERASE; while(1){;};
        }
        else if ((rdstatus & SR5) != 0)
        {
            // Erase Error
            errorcode=MEMD_ERR_ERASE; while(1){;};
        }
        else if ((rdstatus & SR1) != 0)
        {
            errorcode=MEMD_ERR_PROTECT; while(1){;};
        }
        
        // Reset to read array mode when every block erase operation is finished.
	status = hal_SysEnterCriticalSection();
        *BankAddr = CMD_READ_ARRAY;
        hal_SysExitCriticalSection(status);

	// Clear status register if any error 
	if(errorcode != MEMD_ERR_NO)
	{
    while(1){;};
	    status = hal_SysEnterCriticalSection();
            *BankAddr = CMD_CLR_STATUS_REG;
            hal_SysExitCriticalSection(status);
	    hal_EbcFlashWriteEnable(FALSE);
            return errorcode;
	}

        if (phy_End != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(phy_End, &phy_Start, &phy_End);
        } else
        {
            phy_Start = phy_End;
        }
    }
    if (BankAddr != NULL)
    {
        // Return to Read Array mode
        status = hal_SysEnterCriticalSection();
        *BankAddr = CMD_READ_ARRAY;
        hal_SysExitCriticalSection(status);
    }

    // erase done
    hal_EbcFlashWriteEnable(FALSE);
    return errorcode;
}
示例#2
0
// =============================================================================
// memd_FlashWrite
// -----------------------------------------------------------------------------
/// This function writes data in the flash. It gets its data from \c buffer, copies 
/// \c byteSize bytes to the flash location designed by \c flashAddress. \c 
/// pWrittenbyteSize is filled with the actual number of written bytes (Equal 
/// to size, or less in case of error).
/// 
/// @param  flashAddress The byte offset within the flash chip. (Take care not 
/// to overwrite the code present at the beginning of the flash)
/// @param  byteSize Number of bytes to write in flash
/// @param  pWrittenbyteSize Number of bytes actually written in flash
/// @param  buffer Buffer where to get the data to write in the flash
/// @return #MEMD_ERR_NO, #MEMD_ERR_WRITE or #MEMD_ERR_PROTECT
/// whether the operation succeeded or failed.
// =============================================================================
PUBLIC MEMD_ERR_T memd_FlashWrite(UINT8 *flashAddress,
        UINT32 byteSize, 
        UINT32 * pWrittenbyteSize, 
        CONST UINT8* buffer)
{
    VOLATILE UINT16 * BankAddr;
    VOLATILE UINT16 * ptr;
    UINT16 data;
    UINT32 bsize=0;
    UINT32 wsize=0;
    UINT32 owsize=0;
    MEMD_ERR_T errorcode=MEMD_ERR_NO;
    UINT32 status;
    UINT32 phys_add;
    UINT32 phy_SectAddr;
    UINT32 phy_End;
    BOOL isLocked;
    UINT16 rdstatus;


    *pWrittenbyteSize=0;
    if (byteSize==0)
    {
        return MEMD_ERR_NO;
    }

    hal_EbcFlashWriteEnable(TRUE);

    phys_add = (UINT32)flashAddress;
    MEMD_ASSERT((phys_add & 0xe0000000) == 0,
        "flash_address is expected to be a byte offset within the flash chip, not an absolute address")

    memd_FlashGetSectorLimits((UINT32)flashAddress, &phy_SectAddr, &phy_End);
    BankAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&FLASHBANK_MASK));
    ptr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&~1));

    // Unlock block
    memd_FlashGetLockStatus((UINT8*)((UINT32)phy_SectAddr & MY_MASK),&isLocked);
	hal_EbcFlashWriteEnable(TRUE);
    if(isLocked == TRUE)
        memd_BlockLock((UINT8*)((UINT32)phy_SectAddr & MY_MASK),NULL,FALSE);

    if ((phys_add&1) == 1)
    {
        data = *(ptr);
    } else {
        data = (*buffer) | ~0x00ff;
        buffer ++;
        bsize ++;
    }
    if (bsize<byteSize)
    {
        data = data & (((*buffer) << 8) | 0x00ff);
        buffer ++;
        bsize ++;
    }

    if (bsize==byteSize)
    {
        // last byte
        data = data & *(ptr);
    }
    // first byte is prepared
    /* 16b data ready write it to flash*/
    status = hal_SysEnterCriticalSection();
    *(BankAddr) = CMD_PROG;
    *(ptr)=data;
    hal_SysExitCriticalSection(status);

    while(bsize<byteSize) {
        UINT16 tdata;
        VOLATILE UINT16 * tptr;

        // do the next data preparation before the pooling so we are ready to do a new programming just after pooling is OK.
        tdata = data;
        tptr = ptr;

        owsize = wsize;

        wsize = bsize;
        ptr+=1;


        if (bsize<byteSize) {
            data = (*buffer) | ~0x00ff;
            buffer ++;
            bsize ++;
        }
        if(bsize<byteSize) {
            data = data & (((*buffer) << 8) | 0x00ff);
            buffer ++;
            bsize ++;
        }

        // pooling
        // 

	do{
           rdstatus = *BankAddr;
	}while((rdstatus & SR7) != SR7);
        
        // Should probably fix this scheme for reporting errors more cleanly.
        // For now, just prioritize the errors with the most significant error returned
        // in errorcode (order this list from least to most significant)
        if ((rdstatus & SR4) != 0)
        {
            // Some other programming error, should be decoded, but maybe do it later
            errorcode=MEMD_ERR_WRITE;
        }
        else if ((rdstatus & SR1) != 0)
        {
            errorcode=MEMD_ERR_PROTECT;
        }

        if (errorcode!=MEMD_ERR_NO) break;
        if(bsize==byteSize) {
            /* last byte */
            *BankAddr = CMD_READ_ARRAY;
            data = data & *(ptr);
        }
        /* 16b data ready write it to flash*/
        status = hal_SysEnterCriticalSection();
        *(BankAddr) = CMD_PROG;
        *(ptr)=data;
        hal_SysExitCriticalSection(status);
    }
    if (errorcode!=MEMD_ERR_NO)
    {
        wsize = owsize;
    } else
    {
        // last data pooling
        do{
           rdstatus = *BankAddr;
	}while((rdstatus & SR7) != SR7);
     
        if ((rdstatus & SR4) != 0)
        {
            // Some other programming error, should be decoded, but maybe do it later
            errorcode=MEMD_ERR_WRITE;
        }
        else if ((rdstatus & SR1) != 0)
        {
            errorcode=MEMD_ERR_PROTECT;
        }

        wsize = bsize;
    }
		
    *pWrittenbyteSize = wsize;
  
    // return to Read Array mode
    status = hal_SysEnterCriticalSection();
    *BankAddr = CMD_READ_ARRAY;
    hal_SysExitCriticalSection(status);
       
    if(errorcode != MEMD_ERR_NO)
    {
    	status = hal_SysEnterCriticalSection();
        *BankAddr = CMD_CLR_STATUS_REG;          
        hal_SysExitCriticalSection(status);
    }

    hal_EbcFlashWriteEnable(FALSE);
    return errorcode;
}
示例#3
0
// =============================================================================
// memd_BlockLock
// -----------------------------------------------------------------------------
/// This Locks or Unlocks a block (sector) or range of blocks.
/// Flash Write Enable must already be set.
///
/// @param phy_startFlshAddr Start address of the block in flash to start
/// locking.  This must be aligned on a block.
/// @param phy_endFlshAddr End address of the block in flash to stop locking
/// (inclusive).  This must also be aligned on a block.  If this parameter is
/// NULL, then only one block (starting at phy_startFlshAddr) will be locked.
/// @return MEMD_ERR_T error type (alignment errors only)
// =============================================================================
PRIVATE MEMD_ERR_T memd_BlockLock(UINT8 *phy_startFlshAddr, UINT8 *phy_endFlshAddr, BOOL Lock)
{
    UINT32 phy_Start;
    UINT32 phy_End;
    UINT32 status;
    VOLATILE UINT16 * CurBankAddr;
    VOLATILE UINT16 * PrevBankAddr;

    // Check that start & end addresses are aligned
    if (phy_endFlshAddr == NULL)
    {
        memd_FlashGetSectorLimits((UINT32)phy_startFlshAddr, &phy_Start, &phy_End);
        phy_endFlshAddr = (UINT8*)phy_End;
    } else
    {
        if ((UINT32)phy_endFlshAddr != FLASH_SIZE) {
            memd_FlashGetSectorLimits((UINT32)phy_endFlshAddr , &phy_Start, &phy_End);
            if ((UINT32)phy_endFlshAddr != phy_Start) {
                return MEMD_ERR_ALIGN;
            }
        }
    }

    memd_FlashGetSectorLimits((UINT32)phy_startFlshAddr, &phy_Start, &phy_End);
    if ((UINT32)phy_startFlshAddr != phy_Start)
    {
        return MEMD_ERR_ALIGN;
    }

    PrevBankAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phy_Start&FLASHBANK_MASK));

    while (phy_Start != (UINT32)phy_endFlshAddr)
    {
        VOLATILE UINT16 * SectAddr;
        SectAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + phy_Start);
        CurBankAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phy_Start&FLASHBANK_MASK));
        status = hal_SysEnterCriticalSection();
        // If Bank Address is the same as previous Bank Address, continue
        // otherwise, need to put old Bank into Read Array mode and
        // open new Bank.
        if (CurBankAddr != PrevBankAddr)
        {
            // Close Prev Bank
            *PrevBankAddr = CMD_READ_ARRAY;
            PrevBankAddr = CurBankAddr;
        }

        // Lock Set/Clr
        if (Lock)
        {
            *SectAddr = CMD_BLOCK_PROT;
            *SectAddr = CMD_BLOCK_LOCK;
        }
        else
        {
            *SectAddr = CMD_BLOCK_PROT;
            *SectAddr = CMD_BLOCK_UNLOCK;
        }
        hal_SysExitCriticalSection(status);

        if (phy_End != FLASH_SIZE) {
            memd_FlashGetSectorLimits(phy_End, &phy_Start, &phy_End);
        } else
        {
            phy_Start = phy_End;
        }
    }

    // Return to Read Array mode
    status = hal_SysEnterCriticalSection();
    *PrevBankAddr = CMD_READ_ARRAY;
    hal_SysExitCriticalSection(status);

    return MEMD_ERR_NO;
}
示例#4
0
// =============================================================================
// memd_FlashWrite
// -----------------------------------------------------------------------------
/// This function writes data in the flash. It gets its data from \c buffer, copies 
/// \c byteSize bytes to the flash location designed by \c flashAddress. \c 
/// pWrittenbyteSize is filled with the actual number of written bytes (Equal 
/// to size, or less in case of error).
/// 
/// @param  flashAddress The byte offset within the flash chip. (Take care not 
/// to overwrite the code present at the beginning of the flash)
/// @param  byteSize Number of bytes to write in flash
/// @param  pWrittenbyteSize Number of bytes actually written in flash
/// @param  buffer Buffer where to get the data to write in the flash
/// @return #MEMD_ERR_NO, #MEMD_ERR_WRITE or #MEMD_ERR_PROTECT
/// whether the operation succeeded or failed.
// =============================================================================
PUBLIC MEMD_ERR_T memd_FlashWrite(UINT8 *flashAddress,
        UINT32 byteSize, 
        UINT32 * pWrittenbyteSize, 
        CONST UINT8* buffer)
{
    VOLATILE UINT16 * BankAddr;
    VOLATILE UINT16 * ptr;
    UINT16 rdstatus, data;
    UINT32 bsize=0, wsize=0, owsize=0;
    MEMD_ERR_T errorcode=MEMD_ERR_NO;
    UINT32 status;
    UINT32 phys_add;

    //SXS_TRACE(TSTDOUT,"hal_flash: Flash Write 0x%08x, %d\n", flash_address, bytesize);

    *pWrittenbyteSize=0;
    if (byteSize==0)
    {
        return MEMD_ERR_NO;
    }

    hal_EbcFlashWriteEnable(TRUE);

    phys_add = (UINT32)flashAddress;
    MEMD_ASSERT((phys_add & 0xe0000000) == 0,
        "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse")

    if (GET_PAGE_PHYS(phys_add) <= 2)
    {
        BankAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&FLASHBANK_MASK));
        // Start should already be aligned to sector boundary, so shouldn't need any more masking
        ptr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&~1));
    }
    else  // Page > 2, so remap
    {
        // Bank Address needs to be shifted from its current range to between 0x00C0_0000 - 0x00FF_FFFF
        BankAddr = (VOLATILE UINT16 *)((g_memdFlashBaseAddress + (phys_add&FLASHBANK_MASK)) - ((GET_PAGE_PHYS(phys_add)-3)*0x400000));
        ptr = (VOLATILE UINT16 *)((g_memdFlashBaseAddress + (phys_add&~1)) - ((GET_PAGE_PHYS(phys_add)-3)*0x400000));
        // Configure Page Register
        hal_EbcConfigRemap((HAL_EBC_FLSH_PHYSADD_T)phys_add);
    }

    //SXS_TRACE(TSTDOUT,"hal_flash: BankAddr 0x%08x \n", BankAddr);

    if (!g_memdLockOverride)
    {
        if (memd_LockCheck(BankAddr, (UINT16*)ptr))
        {
            hal_EbcFlashWriteEnable(FALSE);
            return MEMD_ERR_PROTECT;
        }
    }

    // Unlock Bypass Entry
    status = hal_SysEnterCriticalSection();
    *(BankAddr+0x555) = 0xaa;
    *(BankAddr+0x2aa) = 0x55;
    *(BankAddr+0x555) = 0x20;
    hal_SysExitCriticalSection(status);
    //SXS_TRACE(TSTDOUT,"hal_flash: unlock\n");

    if ((phys_add&1) == 1)
    {
        data = *(ptr);
    } else {
        data = (*buffer) | ~0x00ff;
        buffer ++;
        bsize ++;
    }
    if (bsize<byteSize)
    {
        data = data & (((*buffer) << 8) | 0x00ff);
        buffer ++;
        bsize ++;
    }

    if (bsize==byteSize)
    {
        // last byte
        data = data & *(ptr);
    }
    // first byte is prepared
    /* 16b data ready write it to flash*/
    status = hal_SysEnterCriticalSection();
    *(BankAddr) = 0xa0;
    *(ptr)=data;
    hal_SysExitCriticalSection(status);

    while(bsize<byteSize) {
        UINT16 tdata;
        VOLATILE UINT16 * tptr;

        // do the next data preparation before the pooling so we are ready to do a new programming just after pooling is OK.
        tdata = data;
        tptr = ptr;

        owsize = wsize;

        wsize = bsize;
        ptr+=1;


        if (bsize<byteSize) {
            data = (*buffer) | ~0x00ff;
            buffer ++;
            bsize ++;
        }
        if(bsize<byteSize) {
            data = data & (((*buffer) << 8) | 0x00ff);
            buffer ++;
            bsize ++;
        }

        // pooling
        while(1)
        {
            rdstatus = (*tptr);
            // DQ7 = prog value ? ok done
            if (((rdstatus ^ tdata) & 0x80) == 0)
                break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20)
            {
                rdstatus = (*tptr);
                // DQ7 = prog value ? ok done
                if (((rdstatus ^ tdata) & 0x80) == 0)
                    break;
                errorcode=MEMD_ERR_WRITE;
                break;
            }
        }
        if (errorcode!=MEMD_ERR_NO) break;
        if(bsize==byteSize) {
            /* last byte */
            data = data & *(ptr);
        }
        /* 16b data ready write it to flash*/
        status = hal_SysEnterCriticalSection();
        *(BankAddr) = 0xa0;
        *(ptr)=data;
        hal_SysExitCriticalSection(status);
    }
    if (errorcode!=MEMD_ERR_NO)
    {
        wsize = owsize;
    } else
    {
        // last data pooling
        while(1)
        {
            rdstatus = (*ptr);
            // DQ7 = prog value ? ok done
            if (((rdstatus ^ data) & 0x80) == 0)
                break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20)
            {
                rdstatus = (*ptr);
                // DQ7 = prog value ? ok done
                if (((rdstatus ^ data) & 0x80) == 0)
                    break;
                errorcode=MEMD_ERR_WRITE;
                break;
            }
        }
        wsize = bsize;
    }
    
    *pWrittenbyteSize = wsize;
    // Unlock Bypass Exit
    status = hal_SysEnterCriticalSection();
    *(BankAddr) = 0x90;
    *(BankAddr) = 0x00;
    hal_SysExitCriticalSection(status);

    hal_EbcFlashWriteEnable(FALSE);
    return errorcode;
}
示例#5
0
文件: hal_ebc.c 项目: BarryChen/RDA
// ============================================================================
// hal_EbcCsOpen
// ----------------------------------------------------------------------------
/// Enable a CS other than the one for FLASH. The chip selects for 
/// FLASH have been set before by calling #hal_EbcFlashOpen.
/// The enabling of a CS returns the base address of the configured space.
/// The settings are given at the opening of the peripheral on the given 
/// chip select, and must support the external maximal clock as it has been
/// set by the configuring of the CS0 (Flash) chip select.
///
/// @param cs Chip Select to Enable. (HAL_EBC_SRAM and CS2 or above)
/// @param csConfig Configuration for the chip select. The \c csEn enable bit
/// of the mode configuration must be set to 1 there if the chip select
/// of the opened peripheral have to be enabled !
/// @return Base address of the configured space
// ============================================================================
PUBLIC VOID* HAL_BOOT_FUNC hal_EbcCsOpen(HAL_EBC_CS_T cs, CONST HAL_EBC_CS_CFG_T* csConfig)
{
    union 
    {
        UINT32 reg;
        HAL_EBC_TIME_CFG_T bitfield;
    } timeCfgUnion; // union representing the status bitfield in a 32 bits value
         // loadable in the register
    
    union 
    {
        UINT32 reg;
        HAL_EBC_MODE_CFG_T bitfield;
    } modeCfgUnion; // union representing the status bitfield in a 32 bits value
         // loadable in the register     
    
    VOID* retval = NULL;
    
    //ENTER CRITICAL
    UINT32 status = hal_SysEnterCriticalSection();

    timeCfgUnion.bitfield = csConfig->time;
    modeCfgUnion.bitfield = csConfig->mode;
  
    // Wait if the lock is locked
    hal_EbcWaitReady();
    switch(cs)
    {
        case HAL_EBC_FLASH :
            EBC_ASSERT(FALSE, "Improper use of the hal_EbcCsOpen function."
                    "It cannot be used to open CS0 ! Use hal_EbcFlashOpen"
                    " to do that.");
            break;

         case HAL_EBC_SRAM :
            // Write the pointer into the table
            //g_halEbcCsConfigArray[1]         = csConfig;
            hwp_memBridge->CS_Time_Write          = timeCfgUnion.reg;
            hwp_memBridge->CS_Config[1].CS_Mode   = modeCfgUnion.reg;

            // Save the config in the Boot Sector structure, so that
            // it can be used by the Boot Sector code to configure the
            // EBC CS RAM mode and timings, it is especially useful
            // in burst mode.
            hal_BootSectorSetEbcConfig(timeCfgUnion.reg, modeCfgUnion.reg);

            retval = (VOID*)hwp_cs1;
            break;

        case HAL_EBC_CS2 :
            // Write the pointer into the table
            //g_halEbcCsConfigArray[2]         = csConfig;
            hwp_memBridge->CS_Time_Write          = timeCfgUnion.reg;
            hwp_memBridge->CS_Config[2].CS_Mode   = modeCfgUnion.reg;

            retval = (VOID*)hwp_cs2;
            break;
            
        case HAL_EBC_CS3 :
            //g_halEbcCsConfigArray[3]         = csConfig;
            hwp_memBridge->CS_Time_Write          = timeCfgUnion.reg;
            hwp_memBridge->CS_Config[3].CS_Mode   = modeCfgUnion.reg;

            retval = (VOID*)hwp_cs3;
            break;
            
        case HAL_EBC_CS4:
            //g_halEbcCsConfigArray[4]         = csConfig;
            hwp_memBridge->CS_Time_Write          = timeCfgUnion.reg;
            hwp_memBridge->CS_Config[4].CS_Mode   = modeCfgUnion.reg;

            retval = (VOID*)hwp_cs4;
            break;

        default:
            break;
    }

    //EXIT CRITICAL
    hal_SysExitCriticalSection(status);

    return retval;
}
示例#6
0
// =============================================================================
// memd_FlashErase
// -----------------------------------------------------------------------------
/// This function erases contiguous flash sectors. 
/// Addresses <B> must be aligned on sectors</B>:
/// - The \c startFlashAddress is the address of the first sector to erase.
/// - The \c endFlashAddress is the address of the first sector NOT to erase.
///   If \c endFlashAddress is \c NULL, only one sector will be erased.
/// .
/// Care must be taken not to erase the code present at the beginning of the flash.
///
/// @param start_flashAddress The address of the first sector to erase
/// @param end_flashAddress The address of the first sector NOT to erase.
///   If \c NULL, only one sector will be erased 
/// @return #MEMD_ERR_NO, #MEMD_ERR_ERASE, #MEMD_ERR_ALIGN or #MEMD_ERR_PROTECT
/// whether the operation succeeded or failed
///
// =============================================================================
PUBLIC MEMD_ERR_T memd_FlashErase(UINT8 *startFlashAddress, UINT8 *endFlashAddress)
{
    UINT8 rdstatus, rdstatus_old;
    UINT32 status;
    VOLATILE UINT8 * ptr;
    VOLATILE UINT16 *BankAddr;
    UINT32 Start, End;
    UINT32 phys_end_add, phys_start_add;

    phys_start_add = (UINT32)startFlashAddress;
    MEMD_ASSERT((phys_start_add & 0xe0000000) == 0, 
        "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse");

    // Check that start & end addresses are aligned
    if (endFlashAddress == NULL)
    {
        memd_FlashGetSectorLimits(phys_start_add, &Start, &End);
        phys_end_add = End;
    } else
    {
        phys_end_add = (UINT32)endFlashAddress;
        MEMD_ASSERT((phys_end_add & 0xe0000000) == 0, 
            "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse")
        if (phys_end_add != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(phys_end_add , &Start, &End);
            if (phys_end_add != Start)
            {
                return MEMD_ERR_ALIGN;
            }
        }
    }

    memd_FlashGetSectorLimits(phys_start_add, &Start, &End);
    if (phys_start_add != Start)
    {
        return MEMD_ERR_ALIGN;
    }

    hal_EbcFlashWriteEnable(TRUE);

    while (Start != phys_end_add)
    {
        if (GET_PAGE_PHYS(Start) <= 2)
        {
            BankAddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (Start&FLASHBANK_MASK));
            // Start should already be aligned to sector boundary, so shouldn't need any more masking
            ptr = (VOLATILE UINT8 *)(g_memdFlashBaseAddress + Start);
        }
        else  // Page > 2, so remap
        {
            // Bank Address needs to be shifted from its current range to between 0x00C0_0000 - 0x00FF_FFFF
            BankAddr = (VOLATILE UINT16 *)((g_memdFlashBaseAddress + (Start&FLASHBANK_MASK)) - ((GET_PAGE_PHYS(Start)-3)*0x400000));
            ptr = (VOLATILE UINT8 *)((g_memdFlashBaseAddress + Start) - ((GET_PAGE_PHYS(Start)-3)*0x400000));
            // Configure Page Register
            hal_EbcConfigRemap((HAL_EBC_FLSH_PHYSADD_T)Start);
        }

        //SXS_TRACE(TSTDOUT,"hal_flash: erase BankAddr 0x%08x, Page %d \n", BankAddr, GET_PAGE_PHYS(Start));
        //SXS_TRACE(TSTDOUT,"hal_flash: erase ptr 0x%08x \n", ptr);
        if (!g_memdLockOverride)
        {
            if (memd_LockCheck(BankAddr, (UINT16*)ptr))
            {
                hal_EbcFlashWriteEnable(FALSE);
                return MEMD_ERR_PROTECT;
            }
        }

        status = hal_SysEnterCriticalSection();
        // Sector Erase command
        *(BankAddr+0x555) = 0xaa;
        *(BankAddr+0x2aa) = 0x55;
        *(BankAddr+0x555) = 0x80;
        *(BankAddr+0x555) = 0xaa;
        *(BankAddr+0x2aa) = 0x55;
        *(ptr) = 0x30;
        hal_SysExitCriticalSection(status);

        // note the pooling could be done on data == 0xff also
    
        // pooling
        rdstatus = (*ptr);
        while(1){
            rdstatus_old = rdstatus;
            rdstatus = (*ptr);
            // DQ6 & DQ2 not toggling? => done
            if (((rdstatus ^ rdstatus_old) & 0x44) == 0)
            break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20) {
                rdstatus_old = (*ptr);
                rdstatus = (*ptr);
                // DQ6 & DQ2 not toggling? => done
                if (((rdstatus ^ rdstatus_old) & 0x44) == 0)
                    break;
                // reset
                (*BankAddr) = 0xf0;
                hal_EbcFlashWriteEnable(FALSE);
                return MEMD_ERR_ERASE;
            }
        }
        if (End != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(End, &Start, &End);
        } else
        {
            Start = End;
        }
    }
    // erase done
    hal_EbcFlashWriteEnable(FALSE);
    return MEMD_ERR_NO;
}
示例#7
0
// =============================================================================
// memd_FlashWrite
// -----------------------------------------------------------------------------
/// This function writes data in the flash. It gets its data from \c buffer, copies 
/// \c byteSize bytes to the flash location designed by \c flashAddress. \c 
/// pWrittenbyteSize is filled with the actual number of written bytes (Equal 
/// to size, or less in case of error).
/// 
/// @param  flashAddress The byte offset within the flash chip. (Take care not 
/// to overwrite the code present at the beginning of the flash)
/// @param  byteSize Number of bytes to write in flash
/// @param  pWrittenbyteSize Number of bytes actually written in flash
/// @param  buffer Buffer where to get the data to write in the flash
/// @return #MEMD_ERR_NO, #MEMD_ERR_WRITE or #MEMD_ERR_PROTECT
/// whether the operation succeeded or failed.
// =============================================================================
PUBLIC MEMD_ERR_T memd_FlashWrite(UINT8 *flashAddress,
        UINT32 byteSize, 
        UINT32 * pWrittenbyteSize, 
        CONST UINT8* buffer)
{
    VOLATILE UINT16 * flashaddr;
    VOLATILE UINT16 * ptr;
    UINT16 rdstatus, data;
    UINT32 bsize=0, wsize=0, owsize=0;
    MEMD_ERR_T errorcode=MEMD_ERR_NO;
    UINT32 status;
    UINT32 phys_add;


    *pWrittenbyteSize=0;
    if (byteSize==0)
    {
        return MEMD_ERR_NO;
    }

    hal_EbcFlashWriteEnable(TRUE);

    phys_add = (UINT32)flashAddress;
    hal_HstSendEvent(0x555500);
    hal_HstSendEvent(phys_add); 
    
    MEMD_ASSERT((phys_add & 0xe0000000) == 0,
        "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse")

    flashaddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&FLASHBANK_MASK));

    if (!g_memdDybOverride)
    {
        ptr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&~0xfff));
        if (memd_DYBCheck(flashaddr, (UINT16*)ptr))
        {
            hal_EbcFlashWriteEnable(FALSE);
            return MEMD_ERR_PROTECT;
        }
    }

    ptr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (phys_add&~1));

    // Unlock Bypass Entry
    status = hal_SysEnterCriticalSection();
    *(flashaddr+0x555) = 0xaa;
    *(flashaddr+0x2aa) = 0x55;
    *(flashaddr+0x555) = 0x20;
    hal_SysExitCriticalSection(status);

    if ((phys_add&1) == 1)
    {
        data = *(ptr);
    } else {
        data = (*buffer) | ~0x00ff;
        buffer ++;
        bsize ++;
    }
    if (bsize<byteSize)
    {
        data = data & (((*buffer) << 8) | 0x00ff);
        buffer ++;
        bsize ++;
    }

    if (bsize==byteSize)
    {
        // last byte
        data = data & *(ptr);
    }
    // first byte is prepared
    /* 16b data ready write it to flash*/
    status = hal_SysEnterCriticalSection();
    *(flashaddr) = 0xa0;
    *(ptr)=data;
    hal_SysExitCriticalSection(status);

    while(bsize<byteSize) {
        UINT16 tdata;
        VOLATILE UINT16 * tptr;

        // do the next data preparation before the pooling so we are ready to do a new programming just after pooling is OK.
        tdata = data;
        tptr = ptr;

        owsize = wsize;

        wsize = bsize;
        ptr+=1;


        if (bsize<byteSize) {
            data = (*buffer) | ~0x00ff;
            buffer ++;
            bsize ++;
        }
        if(bsize<byteSize) {
            data = data & (((*buffer) << 8) | 0x00ff);
            buffer ++;
            bsize ++;
        }

        // pooling
        while(1)
        {
            rdstatus = (*tptr);
            // DQ7 = prog value ? ok done
            if (((rdstatus ^ tdata) & 0x80) == 0)
                break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20)
            {
                rdstatus = (*tptr);
                // DQ7 = prog value ? ok done
                if (((rdstatus ^ tdata) & 0x80) == 0)
                    break;
                errorcode=MEMD_ERR_WRITE;
                break;
            }
        }
        if (errorcode!=MEMD_ERR_NO) break;
        if(bsize==byteSize) {
            /* last byte */
            data = data & *(ptr);
        }
        /* 16b data ready write it to flash*/
        status = hal_SysEnterCriticalSection();
        *(flashaddr) = 0xa0;
        *(ptr)=data;
        hal_SysExitCriticalSection(status);
    }
    if (errorcode!=MEMD_ERR_NO)
    {
        wsize = owsize;
    } else
    {
        // last data pooling
        while(1)
        {
            rdstatus = (*ptr);
            // DQ7 = prog value ? ok done
            if (((rdstatus ^ data) & 0x80) == 0)
                break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20)
            {
                rdstatus = (*ptr);
                // DQ7 = prog value ? ok done
                if (((rdstatus ^ data) & 0x80) == 0)
                    break;
                errorcode=MEMD_ERR_WRITE;
                break;
            }
        }
        wsize = bsize;
    }
    
    *pWrittenbyteSize = wsize;
    // Unlock Bypass Exit
    status = hal_SysEnterCriticalSection();
    *(flashaddr) = 0x90;
    *(flashaddr) = 0x00;
    hal_SysExitCriticalSection(status);

    hal_EbcFlashWriteEnable(FALSE);
    hal_HstSendEvent(0x555504);
    return errorcode;
}
示例#8
0
// =============================================================================
// memd_FlashErase
// -----------------------------------------------------------------------------
/// This function erases contiguous flash sectors. 
/// Addresses <B> must be aligned on sectors</B>:
/// - The \c startFlashAddress is the address of the first sector to erase.
/// - The \c endFlashAddress is the address of the first sector NOT to erase.
///   If \c endFlashAddress is \c NULL, only one sector will be erased.
/// .
/// Care must be taken not to erase the code present at the beginning of the flash.
///
/// @param start_flashAddress The address of the first sector to erase
/// @param end_flashAddress The address of the first sector NOT to erase.
///   If \c NULL, only one sector will be erased 
/// @return #MEMD_ERR_NO, #MEMD_ERR_ERASE, #MEMD_ERR_ALIGN or #MEMD_ERR_PROTECT
/// whether the operation succeeded or failed
///
// =============================================================================
PUBLIC MEMD_ERR_T memd_FlashErase(UINT8 *startFlashAddress, UINT8 *endFlashAddress)
{
    UINT8 rdstatus, rdstatus_old;
    UINT32 status;
    VOLATILE UINT8 * ptr;
    VOLATILE UINT16 *flashaddr;
    UINT32 Start, End;
    UINT32 phys_end_add, phys_start_add;

    phys_start_add = (UINT32)startFlashAddress;
    MEMD_ASSERT((phys_start_add & 0xe0000000) == 0, 
        "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse");
    hal_HstSendEvent(0x654300); hal_HstSendEvent(phys_start_add); hal_HstSendEvent(0x654301); 
    // Check that start & end addresses are aligned
    if (endFlashAddress == NULL)
    {
        memd_FlashGetSectorLimits(phys_start_add, &Start, &End);
        phys_end_add = End;
    } else
    {
        phys_end_add = (UINT32)endFlashAddress;
        MEMD_ASSERT((phys_end_add & 0xe0000000) == 0, 
            "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse")
        if (phys_end_add != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(phys_end_add , &Start, &End);
            if (phys_end_add != Start)
            {
                return MEMD_ERR_ALIGN;
            }
        }
    }

    memd_FlashGetSectorLimits(phys_start_add, &Start, &End);
    if (phys_start_add != Start)
    {
        return MEMD_ERR_ALIGN;
    }
hal_HstSendEvent(0x654311); 
    hal_EbcFlashWriteEnable(TRUE);

    while (Start != phys_end_add)
    {
        flashaddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (Start&FLASHBANK_MASK));
        ptr = (VOLATILE UINT8 *)(g_memdFlashBaseAddress + (Start&~0xfff));

        if (!g_memdDybOverride)
        {
            if (memd_DYBCheck(flashaddr, (UINT16*)ptr))
            {
                hal_EbcFlashWriteEnable(FALSE);hal_HstSendEvent(0x654314); 
                return MEMD_ERR_PROTECT;
            }
        }

        status = hal_SysEnterCriticalSection();
        // Sector Erase command
        *(flashaddr+0x555) = 0xaa;
        *(flashaddr+0x2aa) = 0x55;
        *(flashaddr+0x555) = 0x80;
        *(flashaddr+0x555) = 0xaa;
        *(flashaddr+0x2aa) = 0x55;
        *(ptr) = 0x30;
        hal_SysExitCriticalSection(status);

        // note the pooling could be done on data == 0xff also
    
        // pooling
        rdstatus = (*ptr);
        while(1){
            rdstatus_old = rdstatus;
            rdstatus = (*ptr);
            // DQ6 & DQ2 not toggling? => done
            if (((rdstatus ^ rdstatus_old) & 0x44) == 0)
            break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20) {
                rdstatus_old = (*ptr);
                rdstatus = (*ptr);
                // DQ6 & DQ2 not toggling? => done
                if (((rdstatus ^ rdstatus_old) & 0x44) == 0)
                    break;
                // reset
                (*flashaddr) = 0xf0;
                hal_EbcFlashWriteEnable(FALSE);hal_HstSendEvent(0x654312); 
                return MEMD_ERR_ERASE;
            }
        }
        if (End != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(End, &Start, &End);
        } else
        {
            Start = End;
        }
    }
    // erase done
    hal_EbcFlashWriteEnable(FALSE);
     hal_HstSendEvent(0x654399);
    return MEMD_ERR_NO;
}
示例#9
0
PUBLIC MEMD_ERR_T memd_FlashErase_Continue(UINT8 *startFlashAddress, UINT8 *endFlashAddress,UINT32 time)
{
    UINT8 rdstatus, rdstatus_old;
    UINT32 status;
    VOLATILE UINT8 * ptr;
    VOLATILE UINT16 *flashaddr;
    UINT32 Start, End;
    UINT32 phys_end_add, phys_start_add;
    UINT32 suspend_time = 0,max_time = 0;
    max_time = time MILLI_SECONDS;
    UINT32 now = hal_TimGetUpTime();

    phys_start_add = (UINT32)startFlashAddress;
    MEMD_ASSERT((phys_start_add & 0xe0000000) == 0, 
        "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse");
    
    // Check that start & end addresses are aligned
    if (endFlashAddress == NULL)
    {
        memd_FlashGetSectorLimits(phys_start_add, &Start, &End);
        phys_end_add = End;
    } else
    {
        phys_end_add = (UINT32)endFlashAddress;
        MEMD_ASSERT((phys_end_add & 0xe0000000) == 0, 
            "flash_address is expected to be a byte offset within the flash chip, not an absolute adresse")
        if (phys_end_add != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(phys_end_add , &Start, &End);
            if (phys_end_add != Start)
            {
                return MEMD_ERR_ALIGN;
            }
        }
    }

    memd_FlashGetSectorLimits(phys_start_add, &Start, &End);
    if (phys_start_add != Start)
    {
        return MEMD_ERR_ALIGN;
    }
    hal_EbcFlashWriteEnable(TRUE);

    while (Start != phys_end_add)
    {
        flashaddr = (VOLATILE UINT16 *)(g_memdFlashBaseAddress + (Start&FLASHBANK_MASK));
        ptr = (VOLATILE UINT8 *)(g_memdFlashBaseAddress + (Start&~0xfff));

        if (!g_memdDybOverride)
        {
            if (memd_DYBCheck(flashaddr, (UINT16*)ptr))
            {
                hal_EbcFlashWriteEnable(FALSE);hal_HstSendEvent(0x654314); 
                return MEMD_ERR_PROTECT;
            }
        }

        status = hal_SysEnterCriticalSection();
        *(ptr) = 0x30;
        hal_SysExitCriticalSection(status);

        // note the pooling could be done on data == 0xff also
    
        // pooling
        rdstatus = (*ptr);
        while(1){
                suspend_time = hal_TimGetUpTime();
                 if (suspend_time - now > max_time) 
                  {
                      status = hal_SysEnterCriticalSection();
                      *(ptr) = 0xb0;
                      hal_SysExitCriticalSection(status);
                      do
                      {
                         rdstatus_old = (*ptr);
                         rdstatus = (*ptr);
                         rdstatus_old &= 0x80;
                         rdstatus &= 0x80;
                        
                      }while (!(rdstatus_old == 0x80 && rdstatus == 0x80));	// Wait for suspend active
                      (*flashaddr) = 0xf0;
                      hal_EbcFlashWriteEnable(FALSE);

                      return MEMD_ERR_SUSPEND;

                  }

          
            rdstatus_old = rdstatus;
            rdstatus = (*ptr);
            // DQ6 & DQ2 not toggling? => done
            if (((rdstatus ^ rdstatus_old) & 0x44) == 0)
            break;
            // DQ5 = 1
            if ((rdstatus & 0x20) == 0x20) {
                rdstatus_old = (*ptr);
                rdstatus = (*ptr);
                // DQ6 & DQ2 not toggling? => done
                if (((rdstatus ^ rdstatus_old) & 0x44) == 0)
                    break;
                // reset
                (*flashaddr) = 0xf0;
                hal_EbcFlashWriteEnable(FALSE);hal_HstSendEvent(0x654312); 
                return MEMD_ERR_ERASE;
            }
        }
        if (End != FLASH_SIZE)
        {
            memd_FlashGetSectorLimits(End, &Start, &End);
        } else
        {
            Start = End;
        }
    }
    // erase done
    hal_EbcFlashWriteEnable(FALSE);
     hal_HstSendEvent(0x653333);
    return MEMD_ERR_NO;
}
示例#10
0
文件: hal_dma.c 项目: BarryChen/RDA
// =============================================================================
// hal_DmaStopStd
// -----------------------------------------------------------------------------
/// Stop a standard transfer in progress. If the remaining size to transfer is
/// less than the defined threshold, that function waits for the end of the 
/// transfert. This behaviour is expected by both the FCS and GEA transfert,
/// as those transfers are blocking functions.
/// 
/// It has previously been tested that the transfer is currently a standard one.
/// @param xferState Pointer where the state of the transfer will be stored 
/// for a later resume.
// =============================================================================
PRIVATE VOID hal_DmaStopStd(HAL_DMA_CFG_T* xferState)
{
    UINT32 status;
    UINT32 remainingSize = 0;

    status = hal_SysEnterCriticalSection();
    remainingSize = hwp_dma->xfer_size;

    if (remainingSize > HAL_DMA_PREEMPT_THSLD)
    {
        // Preempt - stop
        hwp_dma->control |= DMA_STOP_TRANSFER;

        // Wait for the end 
        while (!hal_DmaDone());

        // Really needed ?
        if (hwp_dma->xfer_size == 0)
        {
            // the transfer has finished
            // If an IT was programmed, it will be triggered
            // once we go out of critical section.
            hal_SysExitCriticalSection(status);
            // Remaining size is used by the calling function to 
            // know if there is a transfer to resume.
            xferState->transferSize = 0;
        }
        else
        {
            // Stopping the transfer has triggered the IT
            // We must clear IT as this IRQ is meant to 
            // happen once the stopped transfer is fully 
            // completed (ie NOT now)
            // --> Done automatically by clearing the command 
            // register
            xferState->srcAddr =(CONST UINT8*) hwp_dma->src_addr;
            xferState->dstAddr = (UINT8*) hwp_dma->dst_addr;
            xferState->alterDstAddr = (UINT8*) hwp_dma->sd_dst_addr;
            xferState->pattern = hwp_dma->pattern;
            xferState->transferSize =(UINT16) hwp_dma->xfer_size;
            xferState->mode = g_halDmaMode;

            xferState->userHandler = g_halDmaRegistry;

            g_halDmaRegistry = NULL;

            hwp_dma->control = 0; //clear it and prog of the stopped transfer

            hal_SysExitCriticalSection(status);
        }
    }
    else
    {
        // Too few bytes to transfer, we wait
        hal_SysExitCriticalSection(status);
        // Remaining size is used by the calling function to 
        // know if there is a transfer to resume.
        xferState->transferSize = 0;
        // Fill other fields for coherency ?
        xferState->srcAddr = (CONST UINT8*)0;
        xferState->dstAddr = (UINT8*)0;
        xferState->alterDstAddr = (UINT8*)0;
        xferState->pattern = 0;
        xferState->mode = 0;
        xferState->userHandler = NULL;

        while (!hal_DmaDone());
    }

    g_halDmaUserId = HAL_DMA_NONE;
}