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

📄 nor.c

📁 Freescale ARM9系列CPU MX27的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  File:  flash.c
//
//  This file implements CFI flash memory erase and write functions. Current
//  implementation doesn't support flash/block protection bit and it doesn't
//  use buffer write even if flash supports it. 
//
#include <windows.h>
#include <oal.h>
#include "bsp.h"

//------------------------------------------------------------------------------

static BOOL BitZero(UINT32 code, UINT32 bit, UINT32 width, UINT32 parallel)
{
    BOOL rc = FALSE;
    
    switch (width) {
    case 4:
        if (parallel == 4) {
            rc = (code & (1 << bit)) == 0 || (code & (1 << (bit + 8))) == 0 ||
                (code & (1 << (bit + 16))) == 0 ||
                (code & (1 << (bit + 24))) == 0;
        } else if (parallel == 2) {
            rc = (code & (1 << bit)) == 0 || (code & (1 << (bit + 16))) == 0;
        } else if (parallel == 1) {
            rc = (code & (1 << bit)) == 0;
        }
        break;
    case 2:
        if (parallel == 2) {
            rc = (code & (1 << bit)) == 0 || (code & (1 << (bit + 8))) == 0;
        } else if (parallel == 1) {
            rc = (code & (1 << bit)) == 0;
        }
        break;
    case 1:
        rc = (code & (1 << bit)) == 0;
        break;
    }
    return rc;
}

//------------------------------------------------------------------------------


// 
// adjusts offset for width, reads width worth of data from that address
// 
static UINT32 ReadIdentification(UINT32 base, UINT32 offset, UINT32 width)
{
    UINT32 data = 0;
    
    switch (width) {
    case 4:        
        data = INREG32((UINT32*)(base + (offset << 2)));
        break;
    case 2:        
         data = INREG16((UINT16*)(base + (offset << 1))) & 0xFFFF;
        break;
    case 1:
         data = INREG8((UINT8*)(base + offset)) & 0xFF;
        break;
    }

    return data;            
}


static UINT32 ReadInfo(UINT32 base, UINT32 offset, UINT32 size, UINT32 width)
{
    UINT32 data = 0;
    INT32 count = (INT32)size;
    
    switch (width) {
    case 4:        
        while (count-- > 0) {
            data <<= 8;
            data |= INREG32((UINT32*)(base + ((offset + count) << 2))) & 0xFF;
        }
        break;
    case 2:        
        while (count-- > 0) {
            data <<= 8;
            data |= INREG16((UINT16*)(base + ((offset + count) << 1))) & 0xFF;
        }
        break;
    case 1:
        while (count-- > 0) {
            data <<= 8;
            data |= INREG8((UINT8*)(base + offset + count));
        }
        break;
    }

    return data;            
}

//------------------------------------------------------------------------------

static VOID WriteCommand(
    UINT32 base, UINT32 offset, UINT8 cmd, UINT32 width, UINT32 parallel
) {
    UINT32 code;
        
    switch (width) {
    case 4:
        if (parallel == 4) {
            code = cmd | (cmd << 8) | (cmd << 16) | (cmd << 24);
        } else if (parallel == 2) {
            code = cmd | (cmd << 16);
        } else if (parallel == 1) {
            code = cmd;
        } else {
            break;
        }
        OUTREG32((UINT32*)(base + (offset << 2)), code);
        break;
    case 2:
        if (parallel == 2) {
            code = cmd | (cmd << 8);
        } else if (parallel == 1) {
            code = cmd;
        } else {
            break;
        }
        OUTREG16((UINT16*)(base + (offset << 1)), code);
        break;
    case 1:
        if (parallel != 1) break;
        code = cmd;
        OUTREG8((UINT8*)(base + offset), code);
        break;
    }
}

//------------------------------------------------------------------------------

static BOOL UnlockBlock1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo)
{
    //BOOL rc;
    //UINT32 code;
   
    // Start block unlock
    WriteCommand(base,  0, 0x50, pInfo->width, pInfo->parallel);
    WriteCommand(block, 0, 0x60, pInfo->width, pInfo->parallel);
    WriteCommand(block, 0, 0xD0, pInfo->width, pInfo->parallel);

	// Note: We could (should?) verify the unlock worked

    // Switch back to read mode
    WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);

    return TRUE;
}

//------------------------------------------------------------------------------

static BOOL EraseBlock1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo)
{
    BOOL rc;
    UINT32 code;
   
    // Start block reset
    WriteCommand(base,  0, 0x50, pInfo->width, pInfo->parallel);
    WriteCommand(block, 0, 0x20, pInfo->width, pInfo->parallel);
    WriteCommand(block, 0, 0xD0, pInfo->width, pInfo->parallel);

    // Wait until it is done
    do {
        WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
        code = INREG32((UINT32*)base);
    } while (BitZero(code, 7, pInfo->width, pInfo->parallel));

    // Reset memory back to normal state
    WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);

    // Bit 5 in code is zero if erase succeeded
    rc = BitZero(code, 5, pInfo->width, pInfo->parallel);
    
    // Switch back to read mode
    WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);

    return rc;
}

//------------------------------------------------------------------------------

static BOOL EraseBlock2(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo)
{
    BOOL rc = FALSE;
    UINT32 code, code2;
   
    // Start block reset
    WriteCommand(base, 0x555, 0xAA, pInfo->width, pInfo->parallel);
    WriteCommand(base, 0x2AA, 0x55, pInfo->width, pInfo->parallel);
    WriteCommand(base, 0x555, 0x80, pInfo->width, pInfo->parallel);
    WriteCommand(base, 0x555, 0xAA, pInfo->width, pInfo->parallel);
    WriteCommand(base, 0x2AA, 0x55, pInfo->width, pInfo->parallel);
   
    // Wait until it is done
    switch (pInfo->set) {
    case 2:
        WriteCommand(block, 0, 0x30, pInfo->width, pInfo->parallel);

        // Poll DQ3
        while (TRUE) {
            code = INREG16((UINT16 *)block);
            if (code  & (1U << 3)) break; 
        }

        // Poll DQ7 (done) and DQ5 (error)
        while (TRUE) {
            code = INREG16((UINT16 *)block);

            // DQ7 goes high when successful erase completes
            if (code & (1U << 7)) {
                rc = TRUE;
                break;
            }

            // DQ5 goes high if erase error
            if (code & (1U << 5)) break;
        }

        break;
    case 0x0701:
        WriteCommand(block, 0, 0x80, pInfo->width, pInfo->parallel);
        while (TRUE) {
            code  = INREG32((UINT32*)block);
            code2 = INREG32((UINT32*)block);
            if ((code & (1<<6)) == (code2 & (1<<6)))
                break;
        }
        rc = TRUE;
    }

    // Switch back to read mode
    WriteCommand(base, 0, 0xF0,  pInfo->width, pInfo->parallel);

    return rc;
}

//------------------------------------------------------------------------------

static UINT32 WriteData1(
    ULONG base, ULONG pos, OAL_FLASH_INFO *pInfo, VOID *pBuffer
) {
    UINT32 size = 0, code;

    // Issue write command
    WriteCommand(base, 0, 0x40, pInfo->width, pInfo->parallel);
   
    // Now write info and wait until it is done
    switch (pInfo->width) {
    case 4:
        OUTREG32((UINT32*)pos, *(UINT32*)pBuffer);
        do {
            WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
            code = INREG32((UINT32*)pos);
        } while (BitZero(code, 7, pInfo->width, pInfo->parallel));
        if (BitZero(code, 4, pInfo->width, pInfo->parallel)) size = 4;
        break;
    case 2:
        OUTREG16((UINT16*)pos, *(UINT16*)pBuffer);
        do {
            WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
            code = INREG16((UINT16*)pos);
        } while (BitZero(code, 7, pInfo->width, pInfo->parallel));
        if (BitZero(code, 4, pInfo->width, pInfo->parallel)) size = 2;
        break;
   case 1:
        OUTREG8((UINT8*)pos, *(UINT8*)pBuffer);
        do {
            WriteCommand(base, 0, 0x70, pInfo->width, pInfo->parallel);
            code = INREG8((UINT8*)pos);
        } while (BitZero(code, 7, pInfo->width, pInfo->parallel));
        if (BitZero(code, 4, pInfo->width, pInfo->parallel)) size = 1;
        break;
   }

   // Reset memory back to normal state
   WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);

   // Return result
   return size;
}

//------------------------------------------------------------------------------

static ULONG WriteData2(
    UINT32 base, UINT32 pos, OAL_FLASH_INFO *pInfo, VOID *pBuffer
) {
    UINT32 size = 0, code = 0, code2 = 0;

    // Set flash memory to write mode
    WriteCommand(base, 0x555, 0xAA, pInfo->width, pInfo->parallel);
    WriteCommand(base, 0x2AA, 0x55, pInfo->width, pInfo->parallel);
    WriteCommand(base, 0x555, 0xA0, pInfo->width, pInfo->parallel);

    // Now write info and wait until it is done
    switch (pInfo->width) {
    case 4:
        OUTREG32((UINT32*)pos, *(UINT32*)pBuffer);
        switch (pInfo->set) {
        case 2:
            while (TRUE) {
               code = INREG32((UINT32*)pos);
               if (code == *(UINT32*)pBuffer) break;
               if (BitZero(code, 5, pInfo->width, pInfo->parallel)) continue;
               code = INREG32((UINT32*)pos);
               break;
            }
            break;
        case 0x0701:
            while (TRUE) {
                code  = INREG32((UINT32*)pos);
                code2 = INREG32((UINT32*)pos);
                if ((code & (1<<6)) == (code2 & (1<<6)))
                    break;
            }
            code = INREG32((UINT32*)pos);
            break;
        }
        if (code == *(UINT32*)pBuffer) size = sizeof(UINT32);
        break;
    case 2:
        OUTREG16((UINT16*)pos, *(UINT16*)pBuffer);
        switch (pInfo->set) {
        case 2:
            while (TRUE) {
               code = INREG16((UINT16*)pos);
               if (code == *(UINT16*)pBuffer) break;
               if (BitZero(code, 5, pInfo->width, pInfo->parallel)) continue;
               code = INREG16((UINT16*)pos);
               break;
            }
            break;
        case 0x0701:
            while (TRUE) {
                code  = INREG16((UINT32*)pos);
                code2 = INREG16((UINT32*)pos);
                if ((code & (1<<6)) == (code2 & (1<<6)))
                    break;
            }
            code = INREG16((UINT32*)pos);
            break;
        }
        if (code == *(UINT16*)pBuffer) size = sizeof(UINT16);
        break;
    case 1:
        OUTREG8((UINT8*)pos, *(UINT8*)pBuffer);
        switch (pInfo->set) {
        case 2:
            while (TRUE) {
               code = INREG8((UINT8*)pos);
               if (code == *(UINT8*)pBuffer) break;
               if (BitZero(code, 5, pInfo->width, pInfo->parallel)) continue;
               code = INREG8((UINT8*)pos);
               break;
            }
            break;
        case 0x0701:
            while (TRUE) {
                code  = INREG8((UINT32*)pos);
                code2 = INREG8((UINT32*)pos);
                if ((code & (1<<6)) == (code2 & (1<<6)))
                    break;
            }
            code = INREG8((UINT32*)pos);
            break;
        }
        if (code == *(UINT8*)pBuffer) size = sizeof(UINT8);
        break;
    }

    return size;
}

//------------------------------------------------------------------------------

static BOOL ReadIdent1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo, BYTE* pId, UINT32 count)
{
    UINT32 offset = 0x81;
    UINT32 i = 0;

    // Start read device identification command
    WriteCommand(base,  0, 0x90, pInfo->width, pInfo->parallel);

    // Now read count bytes into the pId buffer 
    // bytes are contiguous, so don't read every other byte
    while (i < count)
    {
        // read a width at the following offset
        UINT32 Ident = ReadIdentification(block, offset, pInfo->width);
        memcpy(pId, &Ident, pInfo->width);
        
        // read a width at a time
        pId += pInfo->width;
        i+= pInfo->width;

        // each width == 1 offset (ie reading 0x81-0x88 with a width = 2 will get 16 bytes)
        offset++;
    }

    // Switch back to read mode
    WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);

    return TRUE;
}

//------------------------------------------------------------------------------

BOOL OALFlashInfo(VOID *pBase, OAL_FLASH_INFO *pInfo)
{
    BOOL rc = FALSE;
    UINT32 base, code1, code2, code3, i;
    

    OALMSG(OAL_FUNC, (L"+OALFlashInfo(0x%08x, ...)\r\n", pBase));

⌨️ 快捷键说明

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