历史上的今天
返回首页

历史上的今天

今天是:2024年09月10日(星期二)

正在发生

2018年09月10日 | 关于STM8S使用硬件SPI收发问题

2018-09-10 来源:eefocus

在调试STM8S的SPI时候,由于在学习板上飞线,然后发现每次读SPI FLASH的设备ID等都是不对的.


在21IC发帖求救http://bbs.21ic.com/forum.php?mod=viewthread&tid=788880&epclose=1


总体来说是怀疑硬件飞线的干扰.于是今天又飞了一块板子,发现仍然有这样的问题.


好吧,真的只能打板了.


自己想想会不会在读取数据前SPI的硬件BUFFER中就存在有数据啊.


嗯,有可能, 于是在读数据前,先将SPI的数据先读出,清空缓存,具体代码如下


/*

 --Common functions

 */

 

/*

 * Function:       Wait_Flash_WarmUp

 * Arguments:      None.

 * Description:    Wait some time until flash read / write enable.

 * Return Message: None.

 */

void Wait_Flash_WarmUp()

{

    uint32 time_cnt = FlashFullAccessTime;

    while( time_cnt > 0 )

    {

        time_cnt--;

    }

}

 

/*

 * Function:       Initial_Spi

 * Arguments:      None

 * Description:    Initial spi flash state and wait flash warm-up

 *                 (enable read/write).

 * Return Message: None

 */

void Initial_Spi()

{

 

#ifdef GPIO_SPI

    WPn = 1;        // Write potected initial high

    SI = 0;         // Flash input data

    SCLK = 1;       // Flash input clock

    CSn = 1;        // Chip Select

#endif

GPIO_Init(CS_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);

GPIO_Init(SPI_SCK_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);

GPIO_Init(SPI_MOSI_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);

GPIO_Init(SPI_MISO_PIN,GPIO_MODE_IN_PU_NO_IT);

 

SPI_DeInit();

SPI_Init(SPI_FIRSTBIT_MSB,SPI_BAUDRATEPRESCALER_2,SPI_MODE_MASTER,SPI_CLOCKPOLARITY_HIGH,\

SPI_CLOCKPHASE_2EDGE,SPI_DATADIRECTION_2LINES_FULLDUPLEX,SPI_NSS_SOFT,0x07);

SPI_Cmd(TRUE);

 

// Wait flash warm-up

    Wait_Flash_WarmUp();

}

 

/*

 * Function:       CS_Low, CS_High

 * Arguments:      None.

 * Description:    Chip select go low / high.

 * Return Message: None.

 */

void CS_Low()

{

#ifdef GPIO_SPI

    CSn = 0;

#else

    //--- insert your chip select code here. ---//

    GPIO_WriteLow(CS_PIN);

#endif

}

 

void CS_High()

{

#ifdef GPIO_SPI

    CSn = 1;

    WPn = 1;

#else

    //--- insert your chip select code here. ---//

    GPIO_WriteHigh(CS_PIN);

#endif

}

 

/*

 * Function:       InsertDummyCycle

 * Arguments:      dummy_cycle, number of dummy clock cycle

 * Description:    Insert dummy cycle of SCLK

 * Return Message: None.

 */

void InsertDummyCycle( uint8 dummy_cycle )

{

#ifdef GPIO_SPI

    uint8 i;

    for( i=0; i < dummy_cycle; i=i+1 )

    {

        SCLK = 0;

        SCLK = 1;

    }

#else

    //--- insert your code here. ---//

    uint8 i;

    for( i=0; i < dummy_cycle / 8 ; i=i+1 )

    {

SPI_SendData(DUMMY_BYTE);

    }

#endif

}

 

/*

 * Function:       SendByte

 * Arguments:      byte_value, data transfer to flash

 *                 transfer_type, select different type of I/O mode.

 *                 Seven mode:

 *                 SIO, single IO

 *                 DIO, dual IO

 *                 QIO, quad IO

 *                 PIO, parallel

 *                 DTSIO, double transfer rate SIO

 *                 DTDIO, double transfer rate DIO

 *                 DTQIO, double transfer rate QIO

 * Description:    Send one byte data to flash

 * Return Message: None.

 */

void SendByte( uint8 byte_value, uint8 transfer_type )

{

while(SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);

 

SPI_SendData(byte_value);

 

#ifdef GPIO_SPI

    uint16 i;

    uint8 cycle_cnt;

 

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // single I/O

        cycle_cnt = 8;

        for( i= 0; i < cycle_cnt; i++ )

        {

            if ( (byte_value & IO_MASK) == 0x80 ){

                SI = 1;

            }

            else{

                SI = 0;

            }

            SCLK = 0;

            byte_value = byte_value << 1;

            SCLK = 1;

        }

        break;

#endif

#ifdef DIO

    case DIO: // dual I/O

        cycle_cnt = 4;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);

            byte_value = byte_value << 2;

            SCLK = 1;

        }

        break;

#endif

#ifdef QIO

    case QIO: // quad I/O

        cycle_cnt = 2;

        for( i= 0; i < cycle_cnt; i++ )

        {

            P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase

            byte_value = byte_value << 4;

            SCLK = 1;

        }

        break;

#endif

#ifdef PIO

    case PIO: //  Parallel I/O

        SCLK = 0;

        PO7 = ( (byte_value & IO_MASK)  == IO_MASK )?1:0;

        PO6 = ( (byte_value & 0x40)  == 0x40 )?1:0;

        P3 = (byte_value & 0x3f) | (P3 & 0xc0);

        SCLK = 1;

        break;

#endif

#ifdef DTSIO

    case DTSIO: //  Double transfer rate single I/O

        cycle_cnt = 4;

         for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;

            byte_value = byte_value << 1;

 

            SCLK = 1;

            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;

            byte_value = byte_value << 1;

        }

        break;

#endif

#ifdef DTDIO

    case DTDIO: //  Double transfer rate dual I/O

        cycle_cnt = 2;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);

            byte_value = byte_value << 2;

            SCLK = 1;

            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);

            byte_value = byte_value << 2;

        }

        break;

#endif

#ifdef DTQIO

    case DTQIO: //  Double transfer rate quad I/O

        SCLK = 0;

        P1 = (byte_value & 0xf0);

        SCLK = 1;

        byte_value = byte_value << 4;

        P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase

        break;

#endif

    default:

        break;

    }

#else

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // Single I/O

        //--- insert your code here for single IO transfer. ---//

        break;

#endif

#ifdef DIO

    case DIO: // Dual I/O

        //--- insert your code here for dual IO transfer. ---//

        break;

#endif

#ifdef QIO

    case QIO: // Quad I/O

        //--- insert your code here for quad IO transfer. ---//

        break;

#endif

#ifdef PIO

    case PIO: // Parallel I/O

        //--- insert your code here for parallel IO transfer. ---//

        break;

#endif

#ifdef DTSIO

    case DTSIO: // Double transfer rate Single I/O

        //--- insert your code here for DT single IO transfer. ---//

        break;

#endif

#ifdef DTDIO

    case DTDIO: // Double transfer rate Dual I/O

        //--- insert your code here for DT dual IO transfer. ---//

        break;

#endif

#ifdef DTQIO

    case DTQIO: // Double transfer rate Quad I/O

        //--- insert your code here for DT quad IO transfer. ---//

        break;

#endif

    default:

        break;

    }

#endif  /* End of GPIO_SPI */

}

/*

 * Function:       GetByte

 * Arguments:      byte_value, data receive from flash

 *                 transfer_type, select different type of I/O mode.

 *                 Seven mode:

 *                 SIO, single IO

 *                 DIO, dual IO

 *                 QIO, quad IO

 *                 PIO, parallel IO

 *                 DTSIO, double transfer rate SIO

 *                 DTDIO, double transfer rate DIO

 *                 DTQIO, double transfer rate QIO

 * Description:    Get one byte data to flash

 * Return Message: 8 bit data

 */

uint8 GetByte( uint8 transfer_type )

{

    uint8 data_buf;

data_buf = SPI_ReceiveData();//必须先读取一下,防止接收缓存中存有数据

 

SendByte( DUMMY_BYTE, SIO );

while(SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);

data_buf = SPI_ReceiveData();

 

#ifdef GPIO_SPI

    uint16 i;

    uint8 cycle_cnt;

    data_buf = 0;

    cycle_cnt = 8 >> transfer_type;

 

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // single I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SO = 1;

        // End VIP 8051 GPIO

 

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            if ( SO == 1 ){

                data_buf = (data_buf | (0x80 >> i));

            }

            SCLK = 1;

        }

        break;

#endif

#ifdef DIO

    case DIO: // dual I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        // End VIP 8051 GPIO

 

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            data_buf = data_buf << 2;

            data_buf = ( data_buf | ((P1 & 0x30) >> 4 ) );

            SCLK = 1;

        }

        break;

#endif

#ifdef QIO

    case QIO: // quad I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        SIO2 = 1;

        SIO3 = 1;

        // End VIP 8051 GPIO

        SCLK = 0;

        data_buf = P1 & 0xf0;

        SCLK = 1;

        SCLK = 0;

        data_buf = ((P1 & 0xf0)>> 4)| data_buf;

        SCLK = 1;

        break;

#endif

#ifdef PIO

    case PIO: //  Parallel I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        PO7 = 1;

        PO6 = 1;

        PO5 = 1;

        PO4 = 1;

        PO3 = 1;

        PO2 = 1;

        PO1 = 1;

        PO0 = 1;

        // End VIP 8051 GPIO

        SCLK = 0;

        data_buf = (( P1 & 0x20 )<< 2) | ((P1 & 0x02 ) << 5) | (P3 & 0x3f );

        SCLK = 1;

        break;

#endif

#ifdef DTSIO

    case DTSIO: //  Double transfer rate Single I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SO = 1;

        // End VIP 8051 GPIO

        cycle_cnt = 4;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            if ( SO == 1 ){

                data_buf = (data_buf | ( 0x80 >> (i*2) ));

            }

            SCLK = 1;

            if ( SO == 1 ){

                data_buf = (data_buf | (0x80 >> ((i*2) + 1) ));

            }

        }

        break;

#endif

#ifdef DTDIO

    case DTDIO: //  Double transfer rate Dual I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        // End VIP 8051 GPIO

        cycle_cnt = 2;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            data_buf = data_buf << 2;

            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );

            SCLK = 1;

            data_buf = data_buf << 2;

            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );

        }

        break;

#endif

#ifdef DTQIO

    case DTQIO: //  DTR qual I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        SIO2 = 1;

        SIO3 = 1;

        // End VIP 8051 GPIO

        SCLK = 0;

        data_buf = P1 & 0xf0;

        SCLK = 1;

        data_buf = ( (P1 & 0xf0) >> 4 )| data_buf;

        break;

#endif

    default:

        break;

 

    }

#else

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // Single I/O

        //--- insert your code here for single IO receive. ---//

        break;

#endif

#ifdef DIO

    case DIO: // Dual I/O

        //--- insert your code here for dual IO receive. ---//

        break;

#endif

#ifdef QIO

    case QIO: // Quad I/O

        //--- insert your code here for qual IO receive. ---//

        break;

#endif

#ifdef PIO

    case PIO: // Parallel I/O

        //--- insert your code here for parallel IO receive. ---//

        break;

#endif

#ifdef DTSIO

    case DTSIO: // Double transfer rate Single I/O

        //--- insert your code here for DT single IO receive. ---//

        break;

#endif

#ifdef DTDIO

    case DTDIO: // Double transfer rate Dual I/O

        //--- insert your code here for DT dual IO receive. ---//

        break;

#endif

#ifdef DTQIO

    case DTQIO: // Double transfer rate Qual I/O

        //--- insert your code here for DT quad IO receive. ---//

#endif

    default:

        break;

    }

#endif  /* End of GPIO_SPI */

    return data_buf;

}

 

/*

 * Function:       WaitFlashReady

 * Arguments:      ExpectTime, expected time-out value of flash operations.

 *                 No use at non-synchronous IO mode.

 * Description:    Synchronous IO:

 *                 If flash is ready return TRUE.

 *                 If flash is time-out return FALSE.

 *                 Non-synchronous IO:

 *                 Always return TRUE

 * Return Message: TRUE, FALSE

 */

BOOL WaitFlashReady( uint32 ExpectTime )

{

#ifndef NON_SYNCHRONOUS_IO

    uint32 temp = 0;

    while( IsFlashBusy() )

    {

        if( temp > ExpectTime )

        {

            return FALSE;

        }

        temp = temp + 1;

    }

       return TRUE;

#else

    return TRUE;

#endif

}

 

/*

 * Function:       WaitRYBYReady

 * Arguments:      ExpectTime, expected time-out value of flash operations.

 *                 No use at non-synchronous IO mode.

 * Description:    Synchronous IO:

 *                 If flash is ready return TRUE.

 *                 If flash is time-out return FALSE.

 *                 Non-synchronous IO:

 *                 Always return TRUE

 * Return Message: TRUE, FALSE

 */

BOOL WaitRYBYReady( uint32 ExpectTime )

{

#ifndef NON_SYNCHRONOUS_IO

    uint32 temp = 0;

#ifdef GPIO_SPI

    while( SO == 0 )

#else

    // Insert your code for waiting RYBY (SO) pin ready

#endif

    {

        if( temp > ExpectTime )

        {

            return FALSE;

        }

        temp = temp + 1;

    }

    return TRUE;

 

#else

    return TRUE;

#endif

}

 

/*

 * Function:       IsFlashBusy

 * Arguments:      None.

 * Description:    Check status register WIP bit.

 *                 If  WIP bit = 1: return TRUE ( Busy )

 *                             = 0: return FALSE ( Ready ).

 * Return Message: TRUE, FALSE

 */

BOOL IsFlashBusy( void )

{

    uint8  gDataBuffer;

 

    CMD_RDSR( &gDataBuffer );

    if( (gDataBuffer & FLASH_WIP_MASK)  == FLASH_WIP_MASK )

        return TRUE;

    else

        return FALSE;

}

 

/*

 * Function:       IsFlashQIO

 * Arguments:      None.

 * Description:    If flash QE bit = 1: return TRUE

 *                                 = 0: return FALSE.

 * Return Message: TRUE, FALSE

 */

BOOL IsFlashQIO( void )

{

#ifdef FLASH_NO_QE_BIT

    return TRUE;

#else

    uint8  gDataBuffer;

    CMD_RDSR( &gDataBuffer );

    if( (gDataBuffer & FLASH_QE_MASK) == FLASH_QE_MASK )

        return TRUE;

    else

        return FALSE;

#endif

}

/*

 * Function:       IsFlash4Byte

 * Arguments:      None

 * Description:    Check flash address is 3-byte or 4-byte.

 *                 If flash 4BYTE bit = 1: return TRUE

 *                                    = 0: return FALSE.

 * Return Message: TRUE, FALSE

 */

BOOL IsFlash4Byte( void )

{

#ifdef FLASH_CMD_RDSCUR

    #ifdef FLASH_4BYTE_ONLY

        return TRUE;

    #elif FLASH_3BYTE_ONLY

        return FALSE;

    #else

        uint8  gDataBuffer;

        CMD_RDSCUR( &gDataBuffer );

        if( (gDataBuffer & FLASH_4BYTE_MASK) == FLASH_4BYTE_MASK )

            return TRUE;

        else

            return FALSE;

    #endif

#else

    return FALSE;

#endif

}

/*

 * Function:       SendFlashAddr

 * Arguments:      flash_address, 32 bit flash memory address

 *                 io_mode, I/O mode to transfer address

 *                 addr_4byte_mode,

 * Description:    Send flash address with 3-byte or 4-byte mode.

 * Return Message: None

 */

void SendFlashAddr( uint32 flash_address, uint8 io_mode, uint8 addr_4byte_mode )

{

    /* Check flash is 3-byte or 4-byte mode.

       4-byte mode: Send 4-byte address (A31-A0)

       3-byte mode: Send 3-byte address (A23-A0) */

    if( addr_4byte_mode == TRUE ){

        SendByte( (flash_address >> 24), io_mode ); // A31-A24

    }

    /* A23-A0 */

    SendByte( (flash_address >> 16), io_mode );

    SendByte( (flash_address >> 8), io_mode );

    SendByte( (flash_address), io_mode );

}

 

/*

 * ID Command

 */

 

/*

 * Function:       CMD_RDID

 * Arguments:      Identification, 32 bit buffer to store id

 * Description:    The RDID instruction is to read the manufacturer ID

 *                 of 1-byte and followed by Device ID of 2-byte.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDID( uint32 *Identification )

{

    uint32 temp;

    uint8  gDataBuffer[3];

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send command

    SendByte( FLASH_CMD_RDID, SIO );

 

    // Get manufacturer identification, device identification

    gDataBuffer[0] = GetByte( SIO );

    gDataBuffer[1] = GetByte( SIO );

    gDataBuffer[2] = GetByte( SIO );

 

    // Chip select go high to end a command

    CS_High();

 

    // Store identification

    temp =  (u32)(gDataBuffer[0]);

    temp =  (u32)((temp << 8) | gDataBuffer[1]);

    *Identification =  (u32)((temp << 8) | gDataBuffer[2]);

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_RES

 * Arguments:      ElectricIdentification, 8 bit buffer to store electric id

 * Description:    The RES instruction is to read the Device

 *                 electric identification of 1-byte.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RES( uint8 *ElectricIdentification )

{

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send flash command and insert dummy cycle

    SendByte( FLASH_CMD_RES, SIO );

    InsertDummyCycle( 24 );

 

    // Get electric identification

    *ElectricIdentification = GetByte( SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_REMS

 * Arguments:      REMS_Identification, 16 bit buffer to store id

 *                 fsptr, pointer of flash status structure

 * Description:    The REMS instruction is to read the Device

 *                 manufacturer ID and electric ID of 1-byte.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_REMS( uint16 *REMS_Identification, FlashStatus *fsptr )

{

    uint8  gDataBuffer[2];

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send flash command and insert dummy cycle ( if need )

    // ArrangeOpt = 0x00 will output the manufacturer's ID first

    //            = 0x01 will output electric ID first

    SendByte( FLASH_CMD_REMS, SIO );

    InsertDummyCycle( 16 );

    SendByte( fsptr->ArrangeOpt, SIO );

 

    // Get ID

    gDataBuffer[0] = GetByte( SIO );

    gDataBuffer[1] = GetByte( SIO );

 

    // Store identification informaion

    *REMS_Identification = (gDataBuffer[0] << 8) | gDataBuffer[1];

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Register  Command

 */

 

/*

 * Function:       CMD_RDSR

 * Arguments:      StatusReg, 8 bit buffer to store status register value

 * Description:    The RDSR instruction is for reading Status Register Bits.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDSR( uint8 *StatusReg )

{

    uint8  gDataBuffer;

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send command

    SendByte( FLASH_CMD_RDSR, SIO );

    gDataBuffer = GetByte( SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    *StatusReg = gDataBuffer;

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_WRSR

 * Arguments:      UpdateValue, 8/16 bit status register value to updata

 * Description:    The WRSR instruction is for changing the values of

 *                 Status Register Bits (and configuration register)

 * Return Message: FlashIsBusy, FlashTimeOut, FlashOperationSuccess

 */

#ifdef SUPPORT_WRSR_CR

ReturnMsg CMD_WRSR( uint16 UpdateValue )

#else

ReturnMsg CMD_WRSR( uint8 UpdateValue )

#endif

{

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send command and update value

    SendByte( FLASH_CMD_WRSR, SIO );

    SendByte( UpdateValue, SIO );

#ifdef SUPPORT_WRSR_CR

    SendByte( UpdateValue >> 8, SIO );    // write configuration register

#endif

 

    // Chip select go high to end a flash command

    CS_High();

 

 

    if( WaitFlashReady( WriteStatusRegCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

 

}

 

/*

 * Function:       CMD_RDSCUR

 * Arguments:      SecurityReg, 8 bit buffer to store security register value

 * Description:    The RDSCUR instruction is for reading the value of

 *                 Security Register bits.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDSCUR( uint8 *SecurityReg )

{

    uint8  gDataBuffer;

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Send command

    SendByte( FLASH_CMD_RDSCUR, SIO );

    gDataBuffer = GetByte( SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    *SecurityReg = gDataBuffer;

 

    return FlashOperationSuccess;

 

}

 

/*

 * Function:       CMD_WRSCUR

 * Arguments:      None.

 * Description:    The WRSCUR instruction is for changing the values of

 *                 Security Register Bits.

 * Return Message: FlashIsBusy, FlashOperationSuccess, FlashWriteRegFailed,

 *                 FlashTimeOut

 */

ReturnMsg CMD_WRSCUR( void )

{

    uint8  gDataBuffer;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write WRSCUR command

    SendByte( FLASH_CMD_WRSCUR, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( WriteSecuRegCycleTime ) ){

 

        CMD_RDSCUR( &gDataBuffer );

 

        // Check security register LDSO bit

        if( (gDataBuffer & FLASH_LDSO_MASK) == FLASH_LDSO_MASK )

                return FlashOperationSuccess;

        else

                return FlashWriteRegFailed;

    }

    else

        return FlashTimeOut;

 

}

 

 

/*

 * Read Command

 */

 

/*

 * Function:       CMD_READ

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    The READ instruction is for reading data out.

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_READ( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write READ command and address

    SendByte( FLASH_CMD_READ, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Set a loop to read data into buffer

    for( index=0; index < byte_length; index++ )

    {

        // Read data one byte at a time

        *(target_address + index) = GetByte( SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_DREAD

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    The DREAD instruction enable double throughput of Serial

 *                 Flash in read mode

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_DREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;    // 4-byte mode

    else

        addr_4byte_mode = FALSE;   // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write 2-I/O Read command and address

    SendByte( FLASH_CMD_DREAD, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

    InsertDummyCycle( 8 );                    // Wait 8 dummy cycle

 

    // Set a loop to read data into data buffer

    for( index=0; index < byte_length; index++ )

    {

        *(target_address + index) = GetByte( DIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_FASTREAD

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    The FASTREAD instruction is for quickly reading data out.

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_FASTREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Fast Read command, address and dummy cycle

    SendByte( FLASH_CMD_FASTREAD, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

    InsertDummyCycle ( 8 );          // Wait dummy cycle

 

    // Set a loop to read data into data buffer

    for( index=0; index < byte_length; index++ )

    {

        *(target_address + index) = GetByte( SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_RDSFDP

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    RDSFDP can retrieve the operating characteristics, structure

 *                 and vendor-specified information such as identifying information,

 *                 memory size, operating voltages and timinginformation of device

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_RDSFDP( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Read SFDP command

    SendByte( FLASH_CMD_RDSFDP, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

    InsertDummyCycle ( 8 );        // Insert dummy cycle

 

    // Set a loop to read data into data buffer

    for( index=0; index < byte_length; index++ )

    {

        *(target_address + index) = GetByte( SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

/*

 * Program Command

 */

 

/*

 * Function:       CMD_WREN

 * Arguments:      None.

 * Description:    The WREN instruction is for setting

 *                 Write Enable Latch (WEL) bit.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_WREN( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Enable command = 0x06, Setting Write Enable Latch Bit

    SendByte( FLASH_CMD_WREN, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_WRDI

 * Arguments:      None.

 * Description:    The WRDI instruction is to reset

 *                 Write Enable Latch (WEL) bit.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_WRDI( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Disable command = 0x04, resets Write Enable Latch Bit

    SendByte( FLASH_CMD_WRDI, SIO );

 

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_PP

 * Arguments:      flash_address, 32 bit flash memory address

 *                 source_address, buffer address of source data to program

 *                 byte_length, byte length of data to programm

 * Description:    The PP instruction is for programming

 *                 the memory to be "0".

 *                 The device only accept the last 256 byte ( or 32 byte ) to program.

 *                 If the page address ( flash_address[7:0] ) reach 0xFF, it will

 *                 program next at 0x00 of the same page.

 *                 Some products have smaller page size ( 32 byte )

 * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess,

 *                 FlashTimeOut

 */

ReturnMsg CMD_PP( uint32 flash_address, uint8 *source_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Page Program command

    SendByte( FLASH_CMD_PP, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Set a loop to down load whole page data into flash's buffer

    // Note: only last 256 byte ( or 32 byte ) will be programmed

    for( index=0; index < byte_length; index++ )

    {

        SendByte( *(source_address + index), SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( PageProgramCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

 

/*

 * Erase Command

 */

 

/*

 * Function:       CMD_SE

 * Arguments:      flash_address, 32 bit flash memory address

 * Description:    The SE instruction is for erasing the data

 *                 of the chosen sector (4KB) to be "1".

 * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess,

 *                 FlashTimeOut

 */

ReturnMsg CMD_SE( uint32 flash_address )

{

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Write Sector Erase command = 0x20;

    SendByte( FLASH_CMD_SE, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( SectorEraseCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

 

/*

 * Function:       CMD_BE

 * Arguments:      flash_address, 32 bit flash memory address

 * Description:    The BE instruction is for erasing the data

 *                 of the chosen sector (64KB) to be "1".

 * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess,

 *                 FlashTimeOut

 */

ReturnMsg CMD_BE( uint32 flash_address )

{

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Write Block Erase command = 0xD8;

    SendByte( FLASH_CMD_BE, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( BlockEraseCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

/*

 * Function:       CMD_CE

 * Arguments:      None.

 * Description:    The CE instruction is for erasing the data

 *                 of the whole chip to be "1".

 * Return Message: FlashIsBusy, FlashOperationSuccess, FlashTimeOut

 */

ReturnMsg CMD_CE( void )

{

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Write Chip Erase command = 0x60;

    SendByte( FLASH_CMD_CE, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( ChipEraseCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

 

/*

 * Mode setting Command

 */

 

/*

 * Function:       CMD_DP

 * Arguments:      None.

 * Description:    The DP instruction is for setting the

 *                 device on the minimizing the power consumption.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_DP( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Deep Power Down Mode command

    SendByte( FLASH_CMD_DP, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_RDP

 * Arguments:      None.

 * Description:    The Release from RDP instruction is

 *                 putting the device in the Stand-by Power mode.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDP( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Deep Power Down Mode command

    SendByte( FLASH_CMD_RDP, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_ENSO

 * Arguments:      None.

 * Description:    The ENSO instruction is for entering the secured OTP mode.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_ENSO( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write ENSO command

    SendByte( FLASH_CMD_ENSO, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_EXSO

 * Arguments:      None.

 * Description:    The EXSO instruction is for exiting the secured OTP mode.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_EXSO( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write EXSO command = 0xC1

    SendByte( FLASH_CMD_EXSO, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Reset setting Command

 */

 

/*

 * Security Command

 */


注意在uint8 GetByte( uint8 transfer_type )函数的这句话


data_buf = SPI_ReceiveData();//必须先读取一下,防止接收缓存中存有数据


好了,调试一下,果然成功获取该SPI FLASH的值.


 那我用IO方式验证一下.代码如下:


/*

 --Common functions

 */

 

/*

 * Function:       Wait_Flash_WarmUp

 * Arguments:      None.

 * Description:    Wait some time until flash read / write enable.

 * Return Message: None.

 */

void Wait_Flash_WarmUp()

{

    uint32 time_cnt = FlashFullAccessTime;

    while( time_cnt > 0 )

    {

        time_cnt--;

    }

}

 

/*

 * Function:       Initial_Spi

 * Arguments:      None

 * Description:    Initial spi flash state and wait flash warm-up

 *                 (enable read/write).

 * Return Message: None

 */

void Initial_Spi()

{

 

#ifdef GPIO_SPI

    WPn = 1;        // Write potected initial high

    SI = 0;         // Flash input data

    SCLK = 1;       // Flash input clock

    CSn = 1;        // Chip Select

#endif

GPIO_Init(CS_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);

GPIO_Init(SPI_SCK_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);

GPIO_Init(SPI_MOSI_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);

GPIO_Init(SPI_MISO_PIN,GPIO_MODE_IN_PU_NO_IT);

 

//SPI_DeInit();

//SPI_Init(SPI_FIRSTBIT_MSB,SPI_BAUDRATEPRESCALER_2,SPI_MODE_MASTER,SPI_CLOCKPOLARITY_HIGH,\

// SPI_CLOCKPHASE_2EDGE,SPI_DATADIRECTION_2LINES_FULLDUPLEX,SPI_NSS_SOFT,0x07);

//SPI_Cmd(TRUE);

 

// Wait flash warm-up

    Wait_Flash_WarmUp();

}

 

/*

 * Function:       CS_Low, CS_High

 * Arguments:      None.

 * Description:    Chip select go low / high.

 * Return Message: None.

 */

void CS_Low()

{

#ifdef GPIO_SPI

    CSn = 0;

#else

    //--- insert your chip select code here. ---//

    GPIO_WriteLow(CS_PIN);

#endif

}

 

void CS_High()

{

#ifdef GPIO_SPI

    CSn = 1;

    WPn = 1;

#else

    //--- insert your chip select code here. ---//

    GPIO_WriteHigh(CS_PIN);

#endif

}

 

/*

 * Function:       InsertDummyCycle

 * Arguments:      dummy_cycle, number of dummy clock cycle

 * Description:    Insert dummy cycle of SCLK

 * Return Message: None.

 */

void InsertDummyCycle( uint8 dummy_cycle )

{

#ifdef GPIO_SPI

    uint8 i;

    for( i=0; i < dummy_cycle; i=i+1 )

    {

        SCLK = 0;

        SCLK = 1;

    }

#else

    //--- insert your code here. ---//

    uint8 i;

    #if 0

    for( i=0; i < dummy_cycle / 8 ; i=i+1 )

    {

SPI_SendData(DUMMY_BYTE);

    }

#else

 

 

    for( i=0; i < dummy_cycle; i=i+1 )

    {

GPIO_WriteLow(SPI_SCK_PIN);

GPIO_WriteHigh(SPI_SCK_PIN);

    }

#endif

#endif

}

 

/*

 * Function:       SendByte

 * Arguments:      byte_value, data transfer to flash

 *                 transfer_type, select different type of I/O mode.

 *                 Seven mode:

 *                 SIO, single IO

 *                 DIO, dual IO

 *                 QIO, quad IO

 *                 PIO, parallel

 *                 DTSIO, double transfer rate SIO

 *                 DTDIO, double transfer rate DIO

 *                 DTQIO, double transfer rate QIO

 * Description:    Send one byte data to flash

 * Return Message: None.

 */

void SendByte( uint8 byte_value, uint8 transfer_type )

{

    uint16 i;

    uint8 cycle_cnt;

#if 0

while(SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);

 

SPI_SendData(byte_value);

#else

        cycle_cnt = 8;

        for( i= 0; i < cycle_cnt; i++ )

        {

            if ( (byte_value & IO_MASK) == 0x80 ){

GPIO_WriteHigh(SPI_MOSI_PIN);

            }

            else{

GPIO_WriteLow(SPI_MOSI_PIN);

            }

GPIO_WriteLow(SPI_SCK_PIN);

            byte_value = byte_value << 1;

GPIO_WriteHigh(SPI_SCK_PIN);

        }

 

#endif

#ifdef GPIO_SPI

 

 

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // single I/O

        cycle_cnt = 8;

        for( i= 0; i < cycle_cnt; i++ )

        {

            if ( (byte_value & IO_MASK) == 0x80 ){

                SI = 1;

            }

            else{

                SI = 0;

            }

            SCLK = 0;

            byte_value = byte_value << 1;

            SCLK = 1;

        }

        break;

#endif

#ifdef DIO

    case DIO: // dual I/O

        cycle_cnt = 4;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);

            byte_value = byte_value << 2;

            SCLK = 1;

        }

        break;

#endif

#ifdef QIO

    case QIO: // quad I/O

        cycle_cnt = 2;

        for( i= 0; i < cycle_cnt; i++ )

        {

            P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase

            byte_value = byte_value << 4;

            SCLK = 1;

        }

        break;

#endif

#ifdef PIO

    case PIO: //  Parallel I/O

        SCLK = 0;

        PO7 = ( (byte_value & IO_MASK)  == IO_MASK )?1:0;

        PO6 = ( (byte_value & 0x40)  == 0x40 )?1:0;

        P3 = (byte_value & 0x3f) | (P3 & 0xc0);

        SCLK = 1;

        break;

#endif

#ifdef DTSIO

    case DTSIO: //  Double transfer rate single I/O

        cycle_cnt = 4;

         for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;

            byte_value = byte_value << 1;

 

            SCLK = 1;

            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;

            byte_value = byte_value << 1;

        }

        break;

#endif

#ifdef DTDIO

    case DTDIO: //  Double transfer rate dual I/O

        cycle_cnt = 2;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);

            byte_value = byte_value << 2;

            SCLK = 1;

            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);

            byte_value = byte_value << 2;

        }

        break;

#endif

#ifdef DTQIO

    case DTQIO: //  Double transfer rate quad I/O

        SCLK = 0;

        P1 = (byte_value & 0xf0);

        SCLK = 1;

        byte_value = byte_value << 4;

        P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase

        break;

#endif

    default:

        break;

    }

#else

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // Single I/O

        //--- insert your code here for single IO transfer. ---//

        break;

#endif

#ifdef DIO

    case DIO: // Dual I/O

        //--- insert your code here for dual IO transfer. ---//

        break;

#endif

#ifdef QIO

    case QIO: // Quad I/O

        //--- insert your code here for quad IO transfer. ---//

        break;

#endif

#ifdef PIO

    case PIO: // Parallel I/O

        //--- insert your code here for parallel IO transfer. ---//

        break;

#endif

#ifdef DTSIO

    case DTSIO: // Double transfer rate Single I/O

        //--- insert your code here for DT single IO transfer. ---//

        break;

#endif

#ifdef DTDIO

    case DTDIO: // Double transfer rate Dual I/O

        //--- insert your code here for DT dual IO transfer. ---//

        break;

#endif

#ifdef DTQIO

    case DTQIO: // Double transfer rate Quad I/O

        //--- insert your code here for DT quad IO transfer. ---//

        break;

#endif

    default:

        break;

    }

#endif  /* End of GPIO_SPI */

}

/*

 * Function:       GetByte

 * Arguments:      byte_value, data receive from flash

 *                 transfer_type, select different type of I/O mode.

 *                 Seven mode:

 *                 SIO, single IO

 *                 DIO, dual IO

 *                 QIO, quad IO

 *                 PIO, parallel IO

 *                 DTSIO, double transfer rate SIO

 *                 DTDIO, double transfer rate DIO

 *                 DTQIO, double transfer rate QIO

 * Description:    Get one byte data to flash

 * Return Message: 8 bit data

 */

uint8 GetByte( uint8 transfer_type )

{

    uint8 data_buf;

uint16 i;

    uint8 cycle_cnt;

    data_buf = 0;

 

#if 0

data_buf = SPI_ReceiveData();

 

SendByte( DUMMY_BYTE, SIO );

while(SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);

data_buf = SPI_ReceiveData();

#else

    cycle_cnt = 8;

 

    for( i= 0; i < cycle_cnt; i++ )

    {

GPIO_WriteLow(SPI_SCK_PIN);

        if ( GPIO_ReadInputPin(SPI_MISO_PIN) == 1 ){

            data_buf = (data_buf | (0x80 >> i));

        }

GPIO_WriteHigh(SPI_SCK_PIN);

    }

 

 

#endif

#ifdef GPIO_SPI

    cycle_cnt = 8 >> transfer_type;

 

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // single I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SO = 1;

        // End VIP 8051 GPIO

 

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            if ( SO == 1 ){

                data_buf = (data_buf | (0x80 >> i));

            }

            SCLK = 1;

        }

        break;

#endif

#ifdef DIO

    case DIO: // dual I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        // End VIP 8051 GPIO

 

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            data_buf = data_buf << 2;

            data_buf = ( data_buf | ((P1 & 0x30) >> 4 ) );

            SCLK = 1;

        }

        break;

#endif

#ifdef QIO

    case QIO: // quad I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        SIO2 = 1;

        SIO3 = 1;

        // End VIP 8051 GPIO

        SCLK = 0;

        data_buf = P1 & 0xf0;

        SCLK = 1;

        SCLK = 0;

        data_buf = ((P1 & 0xf0)>> 4)| data_buf;

        SCLK = 1;

        break;

#endif

#ifdef PIO

    case PIO: //  Parallel I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        PO7 = 1;

        PO6 = 1;

        PO5 = 1;

        PO4 = 1;

        PO3 = 1;

        PO2 = 1;

        PO1 = 1;

        PO0 = 1;

        // End VIP 8051 GPIO

        SCLK = 0;

        data_buf = (( P1 & 0x20 )<< 2) | ((P1 & 0x02 ) << 5) | (P3 & 0x3f );

        SCLK = 1;

        break;

#endif

#ifdef DTSIO

    case DTSIO: //  Double transfer rate Single I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SO = 1;

        // End VIP 8051 GPIO

        cycle_cnt = 4;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            if ( SO == 1 ){

                data_buf = (data_buf | ( 0x80 >> (i*2) ));

            }

            SCLK = 1;

            if ( SO == 1 ){

                data_buf = (data_buf | (0x80 >> ((i*2) + 1) ));

            }

        }

        break;

#endif

#ifdef DTDIO

    case DTDIO: //  Double transfer rate Dual I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        // End VIP 8051 GPIO

        cycle_cnt = 2;

        for( i= 0; i < cycle_cnt; i++ )

        {

            SCLK = 0;

            data_buf = data_buf << 2;

            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );

            SCLK = 1;

            data_buf = data_buf << 2;

            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );

        }

        break;

#endif

#ifdef DTQIO

    case DTQIO: //  DTR qual I/O

        // Set VIP 8051 GPIO as input ( need pull to high )

        SIO0 = 1;

        SIO1 = 1;

        SIO2 = 1;

        SIO3 = 1;

        // End VIP 8051 GPIO

        SCLK = 0;

        data_buf = P1 & 0xf0;

        SCLK = 1;

        data_buf = ( (P1 & 0xf0) >> 4 )| data_buf;

        break;

#endif

    default:

        break;

 

    }

#else

    switch( transfer_type )

    {

#ifdef SIO

    case SIO: // Single I/O

        //--- insert your code here for single IO receive. ---//

        break;

#endif

#ifdef DIO

    case DIO: // Dual I/O

        //--- insert your code here for dual IO receive. ---//

        break;

#endif

#ifdef QIO

    case QIO: // Quad I/O

        //--- insert your code here for qual IO receive. ---//

        break;

#endif

#ifdef PIO

    case PIO: // Parallel I/O

        //--- insert your code here for parallel IO receive. ---//

        break;

#endif

#ifdef DTSIO

    case DTSIO: // Double transfer rate Single I/O

        //--- insert your code here for DT single IO receive. ---//

        break;

#endif

#ifdef DTDIO

    case DTDIO: // Double transfer rate Dual I/O

        //--- insert your code here for DT dual IO receive. ---//

        break;

#endif

#ifdef DTQIO

    case DTQIO: // Double transfer rate Qual I/O

        //--- insert your code here for DT quad IO receive. ---//

#endif

    default:

        break;

    }

#endif  /* End of GPIO_SPI */

    return data_buf;

}

 

/*

 * Function:       WaitFlashReady

 * Arguments:      ExpectTime, expected time-out value of flash operations.

 *                 No use at non-synchronous IO mode.

 * Description:    Synchronous IO:

 *                 If flash is ready return TRUE.

 *                 If flash is time-out return FALSE.

 *                 Non-synchronous IO:

 *                 Always return TRUE

 * Return Message: TRUE, FALSE

 */

BOOL WaitFlashReady( uint32 ExpectTime )

{

#ifndef NON_SYNCHRONOUS_IO

    uint32 temp = 0;

    while( IsFlashBusy() )

    {

        if( temp > ExpectTime )

        {

            return FALSE;

        }

        temp = temp + 1;

    }

       return TRUE;

#else

    return TRUE;

#endif

}

 

/*

 * Function:       WaitRYBYReady

 * Arguments:      ExpectTime, expected time-out value of flash operations.

 *                 No use at non-synchronous IO mode.

 * Description:    Synchronous IO:

 *                 If flash is ready return TRUE.

 *                 If flash is time-out return FALSE.

 *                 Non-synchronous IO:

 *                 Always return TRUE

 * Return Message: TRUE, FALSE

 */

BOOL WaitRYBYReady( uint32 ExpectTime )

{

#ifndef NON_SYNCHRONOUS_IO

    uint32 temp = 0;

#ifdef GPIO_SPI

    while( SO == 0 )

#else

    // Insert your code for waiting RYBY (SO) pin ready

#endif

    {

        if( temp > ExpectTime )

        {

            return FALSE;

        }

        temp = temp + 1;

    }

    return TRUE;

 

#else

    return TRUE;

#endif

}

 

/*

 * Function:       IsFlashBusy

 * Arguments:      None.

 * Description:    Check status register WIP bit.

 *                 If  WIP bit = 1: return TRUE ( Busy )

 *                             = 0: return FALSE ( Ready ).

 * Return Message: TRUE, FALSE

 */

BOOL IsFlashBusy( void )

{

    uint8  gDataBuffer;

 

    CMD_RDSR( &gDataBuffer );

    if( (gDataBuffer & FLASH_WIP_MASK)  == FLASH_WIP_MASK )

        return TRUE;

    else

        return FALSE;

}

 

/*

 * Function:       IsFlashQIO

 * Arguments:      None.

 * Description:    If flash QE bit = 1: return TRUE

 *                                 = 0: return FALSE.

 * Return Message: TRUE, FALSE

 */

BOOL IsFlashQIO( void )

{

#ifdef FLASH_NO_QE_BIT

    return TRUE;

#else

    uint8  gDataBuffer;

    CMD_RDSR( &gDataBuffer );

    if( (gDataBuffer & FLASH_QE_MASK) == FLASH_QE_MASK )

        return TRUE;

    else

        return FALSE;

#endif

}

/*

 * Function:       IsFlash4Byte

 * Arguments:      None

 * Description:    Check flash address is 3-byte or 4-byte.

 *                 If flash 4BYTE bit = 1: return TRUE

 *                                    = 0: return FALSE.

 * Return Message: TRUE, FALSE

 */

BOOL IsFlash4Byte( void )

{

#ifdef FLASH_CMD_RDSCUR

    #ifdef FLASH_4BYTE_ONLY

        return TRUE;

    #elif FLASH_3BYTE_ONLY

        return FALSE;

    #else

        uint8  gDataBuffer;

        CMD_RDSCUR( &gDataBuffer );

        if( (gDataBuffer & FLASH_4BYTE_MASK) == FLASH_4BYTE_MASK )

            return TRUE;

        else

            return FALSE;

    #endif

#else

    return FALSE;

#endif

}

/*

 * Function:       SendFlashAddr

 * Arguments:      flash_address, 32 bit flash memory address

 *                 io_mode, I/O mode to transfer address

 *                 addr_4byte_mode,

 * Description:    Send flash address with 3-byte or 4-byte mode.

 * Return Message: None

 */

void SendFlashAddr( uint32 flash_address, uint8 io_mode, uint8 addr_4byte_mode )

{

    /* Check flash is 3-byte or 4-byte mode.

       4-byte mode: Send 4-byte address (A31-A0)

       3-byte mode: Send 3-byte address (A23-A0) */

    if( addr_4byte_mode == TRUE ){

        SendByte( (flash_address >> 24), io_mode ); // A31-A24

    }

    /* A23-A0 */

    SendByte( (flash_address >> 16), io_mode );

    SendByte( (flash_address >> 8), io_mode );

    SendByte( (flash_address), io_mode );

}

 

/*

 * ID Command

 */

 

/*

 * Function:       CMD_RDID

 * Arguments:      Identification, 32 bit buffer to store id

 * Description:    The RDID instruction is to read the manufacturer ID

 *                 of 1-byte and followed by Device ID of 2-byte.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDID( uint32 *Identification )

{

    uint32 temp;

    uint8  gDataBuffer[3];

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send command

    SendByte( FLASH_CMD_RDID, SIO );

 

    // Get manufacturer identification, device identification

    gDataBuffer[0] = GetByte( SIO );

    gDataBuffer[1] = GetByte( SIO );

    gDataBuffer[2] = GetByte( SIO );

 

    // Chip select go high to end a command

    CS_High();

 

    // Store identification

    temp =  (u32)(gDataBuffer[0]);

    temp =  (u32)((temp << 8) | gDataBuffer[1]);

    *Identification =  (u32)((temp << 8) | gDataBuffer[2]);

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_RES

 * Arguments:      ElectricIdentification, 8 bit buffer to store electric id

 * Description:    The RES instruction is to read the Device

 *                 electric identification of 1-byte.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RES( uint8 *ElectricIdentification )

{

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send flash command and insert dummy cycle

    SendByte( FLASH_CMD_RES, SIO );

    InsertDummyCycle( 24 );

 

    // Get electric identification

    *ElectricIdentification = GetByte( SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_REMS

 * Arguments:      REMS_Identification, 16 bit buffer to store id

 *                 fsptr, pointer of flash status structure

 * Description:    The REMS instruction is to read the Device

 *                 manufacturer ID and electric ID of 1-byte.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_REMS( uint16 *REMS_Identification, FlashStatus *fsptr )

{

    uint8  gDataBuffer[2];

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send flash command and insert dummy cycle ( if need )

    // ArrangeOpt = 0x00 will output the manufacturer's ID first

    //            = 0x01 will output electric ID first

    SendByte( FLASH_CMD_REMS, SIO );

    InsertDummyCycle( 16 );

    SendByte( fsptr->ArrangeOpt, SIO );

 

    // Get ID

    gDataBuffer[0] = GetByte( SIO );

    gDataBuffer[1] = GetByte( SIO );

 

    // Store identification informaion

    *REMS_Identification = (gDataBuffer[0] << 8) | gDataBuffer[1];

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Register  Command

 */

 

/*

 * Function:       CMD_RDSR

 * Arguments:      StatusReg, 8 bit buffer to store status register value

 * Description:    The RDSR instruction is for reading Status Register Bits.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDSR( uint8 *StatusReg )

{

    uint8  gDataBuffer;

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send command

    SendByte( FLASH_CMD_RDSR, SIO );

    gDataBuffer = GetByte( SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    *StatusReg = gDataBuffer;

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_WRSR

 * Arguments:      UpdateValue, 8/16 bit status register value to updata

 * Description:    The WRSR instruction is for changing the values of

 *                 Status Register Bits (and configuration register)

 * Return Message: FlashIsBusy, FlashTimeOut, FlashOperationSuccess

 */

#ifdef SUPPORT_WRSR_CR

ReturnMsg CMD_WRSR( uint16 UpdateValue )

#else

ReturnMsg CMD_WRSR( uint8 UpdateValue )

#endif

{

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Send command and update value

    SendByte( FLASH_CMD_WRSR, SIO );

    SendByte( UpdateValue, SIO );

#ifdef SUPPORT_WRSR_CR

    SendByte( UpdateValue >> 8, SIO );    // write configuration register

#endif

 

    // Chip select go high to end a flash command

    CS_High();

 

 

    if( WaitFlashReady( WriteStatusRegCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

 

}

 

/*

 * Function:       CMD_RDSCUR

 * Arguments:      SecurityReg, 8 bit buffer to store security register value

 * Description:    The RDSCUR instruction is for reading the value of

 *                 Security Register bits.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDSCUR( uint8 *SecurityReg )

{

    uint8  gDataBuffer;

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Send command

    SendByte( FLASH_CMD_RDSCUR, SIO );

    gDataBuffer = GetByte( SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    *SecurityReg = gDataBuffer;

 

    return FlashOperationSuccess;

 

}

 

/*

 * Function:       CMD_WRSCUR

 * Arguments:      None.

 * Description:    The WRSCUR instruction is for changing the values of

 *                 Security Register Bits.

 * Return Message: FlashIsBusy, FlashOperationSuccess, FlashWriteRegFailed,

 *                 FlashTimeOut

 */

ReturnMsg CMD_WRSCUR( void )

{

    uint8  gDataBuffer;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write WRSCUR command

    SendByte( FLASH_CMD_WRSCUR, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( WriteSecuRegCycleTime ) ){

 

        CMD_RDSCUR( &gDataBuffer );

 

        // Check security register LDSO bit

        if( (gDataBuffer & FLASH_LDSO_MASK) == FLASH_LDSO_MASK )

                return FlashOperationSuccess;

        else

                return FlashWriteRegFailed;

    }

    else

        return FlashTimeOut;

 

}

 

 

/*

 * Read Command

 */

 

/*

 * Function:       CMD_READ

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    The READ instruction is for reading data out.

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_READ( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write READ command and address

    SendByte( FLASH_CMD_READ, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Set a loop to read data into buffer

    for( index=0; index < byte_length; index++ )

    {

        // Read data one byte at a time

        *(target_address + index) = GetByte( SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_DREAD

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    The DREAD instruction enable double throughput of Serial

 *                 Flash in read mode

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_DREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;    // 4-byte mode

    else

        addr_4byte_mode = FALSE;   // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write 2-I/O Read command and address

    SendByte( FLASH_CMD_DREAD, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

    InsertDummyCycle( 8 );                    // Wait 8 dummy cycle

 

    // Set a loop to read data into data buffer

    for( index=0; index < byte_length; index++ )

    {

        *(target_address + index) = GetByte( DIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_FASTREAD

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    The FASTREAD instruction is for quickly reading data out.

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_FASTREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Fast Read command, address and dummy cycle

    SendByte( FLASH_CMD_FASTREAD, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

    InsertDummyCycle ( 8 );          // Wait dummy cycle

 

    // Set a loop to read data into data buffer

    for( index=0; index < byte_length; index++ )

    {

        *(target_address + index) = GetByte( SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_RDSFDP

 * Arguments:      flash_address, 32 bit flash memory address

 *                 target_address, buffer address to store returned data

 *                 byte_length, length of returned data in byte unit

 * Description:    RDSFDP can retrieve the operating characteristics, structure

 *                 and vendor-specified information such as identifying information,

 *                 memory size, operating voltages and timinginformation of device

 * Return Message: FlashAddressInvalid, FlashOperationSuccess

 */

ReturnMsg CMD_RDSFDP( uint32 flash_address, uint8 *target_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Read SFDP command

    SendByte( FLASH_CMD_RDSFDP, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

    InsertDummyCycle ( 8 );        // Insert dummy cycle

 

    // Set a loop to read data into data buffer

    for( index=0; index < byte_length; index++ )

    {

        *(target_address + index) = GetByte( SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

/*

 * Program Command

 */

 

/*

 * Function:       CMD_WREN

 * Arguments:      None.

 * Description:    The WREN instruction is for setting

 *                 Write Enable Latch (WEL) bit.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_WREN( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Enable command = 0x06, Setting Write Enable Latch Bit

    SendByte( FLASH_CMD_WREN, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_WRDI

 * Arguments:      None.

 * Description:    The WRDI instruction is to reset

 *                 Write Enable Latch (WEL) bit.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_WRDI( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Disable command = 0x04, resets Write Enable Latch Bit

    SendByte( FLASH_CMD_WRDI, SIO );

 

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Function:       CMD_PP

 * Arguments:      flash_address, 32 bit flash memory address

 *                 source_address, buffer address of source data to program

 *                 byte_length, byte length of data to programm

 * Description:    The PP instruction is for programming

 *                 the memory to be "0".

 *                 The device only accept the last 256 byte ( or 32 byte ) to program.

 *                 If the page address ( flash_address[7:0] ) reach 0xFF, it will

 *                 program next at 0x00 of the same page.

 *                 Some products have smaller page size ( 32 byte )

 * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess,

 *                 FlashTimeOut

 */

ReturnMsg CMD_PP( uint32 flash_address, uint8 *source_address, uint32 byte_length )

{

    uint32 index;

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write Page Program command

    SendByte( FLASH_CMD_PP, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Set a loop to down load whole page data into flash's buffer

    // Note: only last 256 byte ( or 32 byte ) will be programmed

    for( index=0; index < byte_length; index++ )

    {

        SendByte( *(source_address + index), SIO );

    }

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( PageProgramCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

 

/*

 * Erase Command

 */

 

/*

 * Function:       CMD_SE

 * Arguments:      flash_address, 32 bit flash memory address

 * Description:    The SE instruction is for erasing the data

 *                 of the chosen sector (4KB) to be "1".

 * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess,

 *                 FlashTimeOut

 */

ReturnMsg CMD_SE( uint32 flash_address )

{

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Write Sector Erase command = 0x20;

    SendByte( FLASH_CMD_SE, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( SectorEraseCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

 

/*

 * Function:       CMD_BE

 * Arguments:      flash_address, 32 bit flash memory address

 * Description:    The BE instruction is for erasing the data

 *                 of the chosen sector (64KB) to be "1".

 * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess,

 *                 FlashTimeOut

 */

ReturnMsg CMD_BE( uint32 flash_address )

{

    uint8  addr_4byte_mode;

 

    // Check flash address

    if( flash_address > FlashSize ) return FlashAddressInvalid;

 

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Check 3-byte or 4-byte mode

    if( IsFlash4Byte() )

        addr_4byte_mode = TRUE;  // 4-byte mode

    else

        addr_4byte_mode = FALSE; // 3-byte mode

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Write Block Erase command = 0xD8;

    SendByte( FLASH_CMD_BE, SIO );

    SendFlashAddr( flash_address, SIO, addr_4byte_mode );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( BlockEraseCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

/*

 * Function:       CMD_CE

 * Arguments:      None.

 * Description:    The CE instruction is for erasing the data

 *                 of the whole chip to be "1".

 * Return Message: FlashIsBusy, FlashOperationSuccess, FlashTimeOut

 */

ReturnMsg CMD_CE( void )

{

    // Check flash is busy or not

    if( IsFlashBusy() )    return FlashIsBusy;

 

    // Setting Write Enable Latch bit

    CMD_WREN();

 

    // Chip select go low to start a flash command

    CS_Low();

 

    //Write Chip Erase command = 0x60;

    SendByte( FLASH_CMD_CE, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    if( WaitFlashReady( ChipEraseCycleTime ) )

        return FlashOperationSuccess;

    else

        return FlashTimeOut;

}

 

 

/*

 * Mode setting Command

 */

 

/*

 * Function:       CMD_DP

 * Arguments:      None.

 * Description:    The DP instruction is for setting the

 *                 device on the minimizing the power consumption.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_DP( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Deep Power Down Mode command

    SendByte( FLASH_CMD_DP, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_RDP

 * Arguments:      None.

 * Description:    The Release from RDP instruction is

 *                 putting the device in the Stand-by Power mode.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_RDP( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Deep Power Down Mode command

    SendByte( FLASH_CMD_RDP, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_ENSO

 * Arguments:      None.

 * Description:    The ENSO instruction is for entering the secured OTP mode.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_ENSO( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write ENSO command

    SendByte( FLASH_CMD_ENSO, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

/*

 * Function:       CMD_EXSO

 * Arguments:      None.

 * Description:    The EXSO instruction is for exiting the secured OTP mode.

 * Return Message: FlashOperationSuccess

 */

ReturnMsg CMD_EXSO( void )

{

    // Chip select go low to start a flash command

    CS_Low();

 

    // Write EXSO command = 0xC1

    SendByte( FLASH_CMD_EXSO, SIO );

 

    // Chip select go high to end a flash command

    CS_High();

 

    return FlashOperationSuccess;

}

 

 

/*

 * Reset setting Command

 */

 

/*

 * Security Command

 */



验证结果也正确的.


推荐阅读

史海拾趣

ABC [ABC Taiwan Electronics Corp]公司的发展小趣事

进入新世纪,ABC Taiwan Electronics Corp面临着产业升级和技术创新的双重挑战。公司加大了对研发的投入,不断推出具有竞争力的新产品。同时,公司还引进了先进的生产设备和管理理念,提升了生产效率和产品质量。通过产业升级和技术创新,ABC成功应对了市场的变化和挑战,保持了稳健的发展态势。

永源微电子(APM)公司的发展小趣事

随着产品线的拓展和技术实力的增强,永源微电子开始积极拓展市场。公司在台湾、深圳、香港、无锡等地设立了研发与销售中心,通过多渠道的市场推广和品牌建设活动,不断提升“APM”品牌的知名度和影响力。同时,永源微电子还积极参加国内外电子行业的展会和交流活动,与业界同行建立了广泛的合作关系,进一步拓展了公司的市场版图。

Embedded Planet公司的发展小趣事

作为一家负责任的企业,Embedded Planet公司一直将绿色环保理念融入产品设计和生产过程中。公司积极采用环保材料和技术,努力降低产品对环境的负面影响。同时,公司还倡导员工参与环保活动,共同为地球的可持续发展贡献力量。这些环保实践不仅提升了公司的社会形象,也为公司赢得了更多客户的信任和支持。

G-Two Inc公司的发展小趣事

背景:2003年,福斯特的创始人林建华,一位在纺织业和化工领域有着丰富经验的工程师,决定跨界进入光伏材料行业。当时,国内光伏组件封装所需的光伏胶膜几乎全部依赖进口,被国外几家大公司垄断。

发展:林建华凭借在热熔网膜领域的技术积累,带领团队成功研发出EVA胶膜,打破了国外技术垄断。这一技术突破不仅降低了国内光伏组件的生产成本,也为福斯特在光伏材料领域的崛起奠定了坚实基础。

成果:2008年,福斯特的EVA胶膜产品凭借优异的性能和价格优势,成功打入国内光伏组件企业的供应名录,并跻身全球EVA胶膜供应商前三强。

AK-Nord_GmbH公司的发展小趣事

AK-Nord_GmbH公司自成立之初,便以技术创新为核心竞争力。在公司发展的早期阶段,团队研发出了一款具有革命性的电源管理芯片,该芯片以其高效能和稳定性迅速赢得了市场的认可。随着技术的不断完善和迭代,公司逐渐在电源管理领域树立了领先地位。随后,AK-Nord_GmbH又投入大量资源进行无线通信技术的研发,成功推出了一系列高性能的无线通信模块,进一步巩固了其在电子行业中的地位。

Eon公司的发展小趣事

E.ON集团的前身可以追溯到1999年,当时德国的两个能源巨头VEBA和VIAG宣布计划在2000年合并。这一合并标志着E.ON的诞生,成为德国乃至欧洲的重要能源公司。合并后,E.ON迅速崭露头角,通过整合双方的资源和优势,迅速占据了德国及欧洲能源市场的重要位置。

问答坊 | AI 解惑

基本有关verilog的书,大家看看吧

[ 本帖最后由 zhangkai0215 于 2009-5-20 09:06 编辑 ]…

查看全部问答>

免费学习matlab---6.16大结局!

对了减少大家的顾虑,积极的参与,而且对于新手来说可能芯币缺乏等原因,对于下载这次matlab的内容,网友只要留下回复,我都会第一时间给你们加芯币,算是免费下载学习的机会吧!!!不过由于一天只能够发2000芯币,希望大家珍惜机会,先报到,先享 ...…

查看全部问答>

推荐几本学习CPLD&FPGA的书

最近一直在学习VHDL ,强烈推荐以下书 1.VHDL硬件描述语言与数字逻辑电路设计(修订版)  侯伯亨 顾新编著 西安电子科技大学出版社 简介:系统地介绍了VHDL 2.现代电子技术 --VHDL与数字系统设计  杨刚 龙海燕编著 电子工 ...…

查看全部问答>

广电筹备3D试播 索尼通吃专业民用市场

本帖最后由 jameswangsynnex 于 2015-3-3 19:56 编辑 欧美日均有3D频道之后,中国的3D电视节目也在酝酿中,内容匮乏的问题现出一线曙光。国家广电总局科技委副主任、副总工程师杜百川日前在“索尼3D世界”发布会上透露,中国今年肯定有部分地区进 ...…

查看全部问答>

如何解决VHDL中参数化赋值:赋全0、全1、全z

VHDL中可将参数定义在generic语句中,一般是将位宽定义在此,其他参数可定义在package中。这里不做讨论。VHDL中一个很好的语句others,对于参数化或者大位宽赋值全0、全1、全X、全Z很方便(这里X、Z为大写),以如下的方式:     &n ...…

查看全部问答>

关于ucf的问题

我现在用xilinx的fpga,有几个pin必须要是某个固定的值,但是我的设计里面是没有相关信号的。如果不去改变code,在ucf里面能否设置这几个pin为我期望的值?…

查看全部问答>

高薪招聘单片机硬件工程师

职能要求: 1.大专以上学历,电子、自动化等相关专业。有三年以上电子类工业产品相关设计工作经验。 2.熟悉电子线路设计,单片机编程; 熟悉PIC、AVR等各种类型单片机。 3.熟练掌握PROTEL、C语言、汇编等各种专业软件。 4.具有产品设计、分析 ...…

查看全部问答>

TI的LM3S9B96学习板上的SRAM是CY62158EV30

不知道有没有便宜的片子替换CY62158EV30啊?…

查看全部问答>

STM32 用AD 实现TFT彩屏的触摸

上次看到论坛上说STM32有一种可以用AD采集实现触摸,可是找不到资料,请问有谁知道的,共享一下。…

查看全部问答>

SPI总线传输距离问题

现在正做毕业设计,需要传输距离几十米,但SPI 穿的距离太近,问老师,老实说:一般可以加一个引脚少的廉价单片机连接器件,使用 单片机的串口利用485接口实现远程通讯。具体加什么器件,怎么实现,求高人,或者告诉我怎么扩展SPI传输距离,拜谢…

查看全部问答>