在调试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 */
验证结果也正确的.