/***************************************************************************** Function: void WF_SpiInit(void) Summary: Initializes the SPI interface to the MRF24WB0M device. Description: Configures the SPI interface for communications with the MRF24WB0M. Precondition: None Parameters: None Returns: None Remarks: This function is called by WFHardwareInit. *****************************************************************************/ void WF_SpiInit(void) { /* disable the spi interrupt */ #if defined( __PIC32MX__ ) WF_SPI_IE_CLEAR = WF_SPI_INT_BITS; #else WF_SPI_IE = 0; #endif #if defined( __18CXX) WF_SPI_IP = 0; #endif // Set up the SPI module on the PIC for communications with the MRF24WB0M WF_CS_IO = 1; WF_CS_TRIS = 0; // Drive SPI MRF24WB0M chip select pin #if defined( __18CXX) WF_SCK_TRIS = 0; /* SPI Clock is an output */ WF_SDO_TRIS = 0; /* SPI Data Out is an output */ WF_SDI_TRIS = 1; /* SPI Data In is an input */ #else // We'll let the module control the pins. #endif #if !defined( SPI_IS_SHARED ) ConfigureSpiMRF24WB0M(); #endif /* clear the completion flag */ ClearSPIDoneFlag(); }
/***************************************************************************** Function: void SPIFlashEraseSector(DWORD dwAddr) Summary: Erases a sector. Description: This function erases a sector in the Flash part. It is called internally by the SPIFlashWrite functions whenever a write is attempted on the first byte in a sector. Precondition: SPIFlashInit has been called. Parameters: dwAddr - The address of the sector to be erased. Returns: None Remarks: See Remarks in SPIFlashBeginWrite for important information about Flash memory parts. ***************************************************************************/ void SPIFlashEraseSector(DWORD dwAddr) { volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif // Save SPI state (clock speed) SPICON1Save = SPIFLASH_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIFLASH_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // Enable writing _SendCmd(WREN); // Activate the chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Issue ERASE command with address SPIFLASH_SSPBUF = ERASE_4K; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwAddr)[2]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwAddr)[1]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwAddr)[0]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; // Deactivate chip select to perform the erase SPIFLASH_CS_IO = 1; // Wait for erase to complete _WaitWhileBusy(); // Restore SPI state SPI_ON_BIT = 0; SPIFLASH_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
void SPIRAMPutROMArray(WORD wAddress, ROM BYTE *vData, WORD wLength) { volatile BYTE Dummy; BYTE vSPIONSave; BYTE SPICON1Save; // Ignore operations when the source data is NULL if(vData == NULL) return; if(wLength == 0u) return; // Save SPI state (clock speed) SPICON1Save = SPIRAM_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIRAM_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // Activate chip select SPIRAM_CS_IO = 0; ClearSPIDoneFlag(); // Send WRITE opcode SPIRAM_SSPBUF = WRITE; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; // Send address SPIRAM_SSPBUF = ((BYTE*)&wAddress)[1]; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; SPIRAM_SSPBUF = ((BYTE*)&wAddress)[0]; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; // Write data while(wLength--) { SPIRAM_SSPBUF = *vData++; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; }; // Deactivate chip select SPIRAM_CS_IO = 1; // Restore SPI state SPI_ON_BIT = 0; SPIRAM_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
/***************************************************************************** Function: static void _SendCmd(BYTE cmd) Summary: Sends a single-byte command to the SPI Flash part. Description: This function sends a single-byte command to the SPI Flash part. It is used for commands such as WREN, WRDI, and EWSR that must have the chip select activated, then deactivated immediately after the command is transmitted. Precondition: SPIFlashInit has been called. Parameters: cmd - The single-byte command code to send Returns: None ***************************************************************************/ static void _SendCmd(BYTE cmd) { // Activate chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Send instruction SPIFLASH_SSPBUF = cmd; WaitForDataByte(); cmd = SPIFLASH_SSPBUF; // Deactivate chip select SPIFLASH_CS_IO = 1; }
/********************************************************************* * Function: BOOL XEEIsBusy(void) * * PreCondition: XEEInit() is already called. * * Input: None * * Output: FALSE if EEPROM is not busy * TRUE if EEPROM is busy * * Side Effects: None * * Overview: Reads the status register * * Note: None ********************************************************************/ BOOL XEEIsBusy(void) { volatile BYTE_VAL result; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif // Save SPI state SPICON1Save = EEPROM_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; EEPROM_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; ASSERT_EEPROM_CS_IO // Send RDSR - Read Status Register opcode EEPROM_SSPBUF = OPCODE_RDSR; WaitForDataByte(); result.Val = EEPROM_SSPBUF; // Get register contents EEPROM_SSPBUF = 0; WaitForDataByte(); result.Val = EEPROM_SSPBUF; DEASSERT_EEPROM_CS_IO // Restore SPI State SPI_ON_BIT = 0; EEPROM_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; ClearSPIDoneFlag(); return result.bits.b0; }
void XEEInit(void) { EEPROM_CS_IO = 1; EEPROM_CS_TRIS = 0; // Drive SPI EEPROM chip select pin EEPROM_SCK_TRIS = 0; // Set SCK pin as an output EEPROM_SDI_TRIS = 1; // Make sure SDI pin is an input EEPROM_SDO_TRIS = 0; // Set SDO pin as an output ClearSPIDoneFlag(); #if defined(__C30__) EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above EEPROM_SPICON2 = 0; EEPROM_SPISTAT = 0; // clear SPI EEPROM_SPISTATbits.SPIEN = 1; #elif defined(__C32__) EEPROM_SPIBRG = (SYS_CLK_PeripheralClockGet()-1ul)/2ul/EEPROM_MAX_SPI_FREQ; EEPROM_SPICON1 = PROPER_SPICON1; #endif }
/***************************************************************************** Function: void WF_SpiEnableChipSelect(void) Summary: Enables the MRF24WB0M SPI chip select. Description: Enables the MRF24WB0M SPI chip select as part of the sequence of SPI communications. Precondition: None Parameters: None Returns: None Remarks: If the SPI bus is shared with other peripherals then the current SPI context is saved. *****************************************************************************/ void WF_SpiEnableChipSelect(void) { #if defined(__18CXX) static volatile UINT8 dummy; #endif #if defined(SPI_IS_SHARED) SaveSpiContext(); ConfigureSpiMRF24WB0M(); #endif /* set Slave Select low (enable SPI chip select on MRF24WB0M) */ WF_CS_IO = 0; /* clear any pending interrupts */ #if defined(__18CXX) dummy = WF_SSPBUF; ClearSPIDoneFlag(); #endif }
void XEEInit(void) { EEPROM_CS_IO = 1; EEPROM_CS_TRIS = 0; // Drive SPI EEPROM chip select pin EEPROM_SCK_TRIS = 0; // Set SCK pin as an output EEPROM_SDI_TRIS = 1; // Make sure SDI pin is an input EEPROM_SDO_TRIS = 0; // Set SDO pin as an output ClearSPIDoneFlag(); #if defined(__C30__) EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above EEPROM_SPICON2 = 0; EEPROM_SPISTAT = 0; // clear SPI EEPROM_SPISTATbits.SPIEN = 1; #elif defined(__C32__) EEPROM_SPIBRG = (GetPeripheralClock()-1ul)/2ul/EEPROM_MAX_SPI_FREQ; EEPROM_SPICON1 = PROPER_SPICON1; #elif defined(__18CXX) EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above EEPROM_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock EEPROM_SPISTATbits.SMP = 0; // Input sampled at middle of data output time #endif }
/***************************************************************************** Function: static void _WaitWhileBusy(void) Summary: Waits for the SPI Flash part to indicate it is idle. Description: This function waits for the SPI Flash part to indicate it is idle. It is used in the programming functions to wait for operations to complete. Precondition: SPIFlashInit has been called. Parameters: None Returns: None ***************************************************************************/ static void _WaitWhileBusy(void) { volatile BYTE Dummy; // Activate chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Send Read Status Register instruction SPIFLASH_SSPBUF = RDSR; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; // Poll the BUSY bit do { SPIFLASH_SSPBUF = 0x00; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; } while(Dummy & BUSY); // Deactivate chip select SPIFLASH_CS_IO = 1; }
/********************************************************************* * Function: XEE_RESULT XEEReadArray(DWORD address, * BYTE *buffer, * WORD length) * * PreCondition: XEEInit() is already called. * * Input: address - Address from where array is to be read * buffer - Caller supplied buffer to hold the data * length - Number of bytes to read. * * Output: XEE_SUCCESS * * Side Effects: None * * Overview: Reads desired number of bytes in sequential mode. * This function performs all necessary steps * and releases the bus when finished. * * Note: None ********************************************************************/ XEE_RESULT XEEReadArray(DWORD address, BYTE *buffer, WORD length) { volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif // Save SPI state (clock speed) SPICON1Save = EEPROM_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; EEPROM_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; ASSERT_EEPROM_CS_IO // Send READ opcode EEPROM_SSPBUF = OPCODE_READ; WaitForDataByte(); Dummy = EEPROM_SSPBUF; // Send address #if defined(USE_EEPROM_25LC1024) EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[2]; WaitForDataByte(); Dummy = EEPROM_SSPBUF; #endif EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[1]; WaitForDataByte(); Dummy = EEPROM_SSPBUF; EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[0]; WaitForDataByte(); Dummy = EEPROM_SSPBUF; while(length--) { EEPROM_SSPBUF = 0; WaitForDataByte(); Dummy = EEPROM_SSPBUF; if(buffer != NULL) *buffer++ = Dummy; }; DEASSERT_EEPROM_CS_IO // Restore SPI state SPI_ON_BIT = 0; EEPROM_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; ClearSPIDoneFlag(); return XEE_SUCCESS; }
static void DoWrite(void) { BYTE i; volatile BYTE vDummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif // Save SPI state SPICON1Save = EEPROM_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; EEPROM_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // Set the Write Enable latch ASSERT_EEPROM_CS_IO EEPROM_SSPBUF = OPCODE_WREN; WaitForDataByte(); vDummy = EEPROM_SSPBUF; DEASSERT_EEPROM_CS_IO // Send WRITE opcode ASSERT_EEPROM_CS_IO EEPROM_SSPBUF = OPCODE_WRITE; WaitForDataByte(); vDummy = EEPROM_SSPBUF; // Send address #if defined(USE_EEPROM_25LC1024) EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[2]; WaitForDataByte(); vDummy = EEPROM_SSPBUF; #endif EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[1]; WaitForDataByte(); vDummy = EEPROM_SSPBUF; EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[0]; WaitForDataByte(); vDummy = EEPROM_SSPBUF; for(i = 0; i < vBytesInBuffer; i++) { // Send the byte to write EEPROM_SSPBUF = EEPROMBuffer[i]; WaitForDataByte(); vDummy = EEPROM_SSPBUF; } // Begin the write DEASSERT_EEPROM_CS_IO // Update write address and clear write cache EEPROMAddress += vBytesInBuffer; vBytesInBuffer = 0; // Restore SPI State SPI_ON_BIT = 0; EEPROM_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; // Wait for write to complete while( XEEIsBusy() ); ClearSPIDoneFlag(); }
/********************************************************************* * Function: void SPIRAMGetArray(WORD wAddress, BYTE *vData, WORD wLength) * * PreCondition: * * Input: * * Output: * * Side Effects: None * * Overview: * * Note: None ********************************************************************/ void SPIRAMGetArray(WORD wAddress, BYTE *vData, WORD wLength) { volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif // Ignore operations when the destination is NULL or nothing to read if(vData == NULL) return; if(wLength == 0u) return; // Save SPI state (clock speed) SPICON1Save = SPIRAM_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIRAM_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // Activate chip select SPIRAM_CS_IO = 0; ClearSPIDoneFlag(); // Send READ opcode SPIRAM_SSPBUF = READ; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; // Send address SPIRAM_SSPBUF = ((BYTE*)&wAddress)[1]; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; SPIRAM_SSPBUF = ((BYTE*)&wAddress)[0]; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; // Read data while(wLength--) { SPIRAM_SSPBUF = 0; WaitForDataByte(); *vData++ = SPIRAM_SSPBUF; }; // Deactivate chip select SPIRAM_CS_IO = 1; // Restore SPI state SPI_ON_BIT = 0; SPIRAM_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
/********************************************************************* * Function: void SPIRAMInit(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Initialize SPI module to communicate to serial * RAM. * * Note: Code sets SPI clock to Fosc/4. ********************************************************************/ void SPIRAMInit(void) { volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif SPIRAM_CS_IO = 1; SPIRAM_CS_TRIS = 0; // Drive SPI RAM chip select pin SPIRAM_SCK_TRIS = 0; // Set SCK pin as an output SPIRAM_SDI_TRIS = 1; // Make sure SDI pin is an input SPIRAM_SDO_TRIS = 0; // Set SDO pin as an output // Save SPI state (clock speed) SPICON1Save = SPIRAM_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIRAM_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; ClearSPIDoneFlag(); #if defined(__C30__) SPIRAM_SPICON2 = 0; SPIRAM_SPISTAT = 0; // clear SPI SPIRAM_SPISTATbits.SPIEN = 1; #elif defined(__C32__) SPIRAM_SPIBRG = (GetPeripheralClock()-1ul)/2ul/SPIRAM_MAX_SPI_FREQ; SPIRAM_SPICON1bits.CKE = 1; SPIRAM_SPICON1bits.MSTEN = 1; SPIRAM_SPICON1bits.ON = 1; #elif defined(__18CXX) SPIRAM_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock SPIRAM_SPISTATbits.SMP = 0; // Input sampled at middle of data output time #endif // Set Burst mode // Activate chip select SPIRAM_CS_IO = 0; // Send Write Status Register opcode SPIRAM_SSPBUF = WRSR; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; // Set status register to 0b01000000 to enable burst mode SPIRAM_SSPBUF = 0x40; WaitForDataByte(); Dummy = SPIRAM_SSPBUF; // Deactivate chip select SPIRAM_CS_IO = 1; // Restore SPI state SPI_ON_BIT = 0; SPIRAM_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
/***************************************************************************** * FUNCTION: zgHALSpiInit * * RETURNS: None * * PARAMS: None * * NOTES: Called by ZGPrvComInit() during init to configure the SPI I/O. *****************************************************************************/ tZGVoidReturn zgHALSpiInit(tZGVoidInput) { /* disable the spi interrupt */ #if defined( __PIC32MX__ ) ZG_SPI_IE_CLEAR = ZG_SPI_INT_BITS; #else ZG_SPI_IE = 0; #endif #if defined( __18CXX) ZG_SPI_IP = 0; #endif // Set up the SPI module on the PIC for communications with the ZG2100 /* enable the SPI pins */ // #if defined(EEPROM_CS_TRIS) // EEPROM_CS_IO = 1; // deselect EEPROM // EEPROM_CS_TRIS = 0; // Drive SPI EEPROM chip select pin // #endif ZG_CS_IO = 1; ZG_CS_TRIS = 0; // Drive SPI ZG2100 chip select pin #if defined( __18CXX) ZG_SCK_TRIS = 0; ZG_SDO_TRIS = 0; ZG_SDI_TRIS = 1; #else // We'll let the module control the pins. #endif /* clear the completion flag */ ClearSPIDoneFlag(); #ifdef DEDICATED_SPI_ZG // Configure the SPI here, instead of every time we access it. /*---------------------------------------------*/ /* Configure SPI I/O for ZG2100 communications */ /*---------------------------------------------*/ /* enable the SPI clocks */ /* set as master */ /* clock idles high */ /* ms bit first */ /* 8 bit tranfer length */ /* data changes on falling edge */ /* data is sampled on rising edge */ /* set the clock divider */ // Set up SPI #if defined(__18CXX) ZG_SPICON1 = 0x30; // SSPEN bit is set, SPI in master mode, (0x30 is for FOSC/4), // IDLE state is high level (0x32 is for FOSC/64) ZG_SPISTATbits.CKE = 0; // Transmit data on falling edge of clock ZG_SPISTATbits.SMP = 1; // Input sampled at end? of data output time #elif defined(__C30__) ZG_SPICON1 = 0x027B; // Fcy Primary prescaler 1:1, secondary prescaler 2:1, CPK=1, CKE=0, SMP=1 ZG_SPICON2 = 0x0000; ZG_SPISTAT = 0x8000; // Enable the module #elif defined( __PIC32MX__ ) ZG_SPI_BRG = (GetPeripheralClock()-1ul)/2ul/ZG_MAX_SPI_FREQ; ZG_SPICON1 = 0x00000260; // sample at end, data change idle to active, clock idle high, master ZG_SPICON1bits.ON = 1; #else #error Configure SPI for the selected processor #endif #endif SPICXT.suppressDoneHandlerCall = FALSE; }
/***************************************************************************** Function: void SPIFlashWriteArray(BYTE* vData, WORD wLen) Summary: Writes an array of bytes to the SPI Flash part. Description: This function writes an array of bytes to the SPI Flash part. When the address pointer crosses a sector boundary (and has more data to write), the next sector will automatically be erased. If the current address pointer indicates an address that is not a sector boundary and is not already erased, the chip will silently ignore the write command until the next sector boundary is crossed. Precondition: SPIFlashInit and SPIFlashBeginWrite have been called, and the current address is either the front of a sector or has already been erased. Parameters: vData - The array to write to the next memory location wLen - The length of the data to be written Returns: None Remarks: See Remarks in SPIFlashBeginWrite for important information about Flash memory parts. ***************************************************************************/ void SPIFlashWriteArray(BYTE* vData, WORD wLen) { volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif BOOL isStarted; BYTE vOpcode; BYTE i; // Do nothing if no data to process if(wLen == 0u) return; // Save SPI state (clock speed) SPICON1Save = SPIFLASH_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIFLASH_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // If starting at an odd address, write a single byte if((dwWriteAddr & 0x01) && wLen) { SPIFlashWrite(*vData); vData++; wLen--; } // Assume we are using AAI Word program mode unless changed later vOpcode = WRITE_WORD_STREAM; isStarted = FALSE; // Loop over all remaining WORDs while(wLen > 1) { // Don't do anything until chip is ready _WaitWhileBusy(); // If address is a sector boundary if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0) SPIFlashEraseSector(dwWriteAddr); // If not yet started, initiate AAI mode if(!isStarted) { // Enable writing _SendCmd(WREN); // Select appropriate programming opcode. The WRITE_WORD_STREAM // mode is the default if neither of these flags are set. if(deviceCaps.bits.bWriteByteStream) vOpcode = WRITE_BYTE_STREAM; else if(deviceCaps.bits.bPageProgram) { // Note: Writing one byte at a time is extremely slow (ex: ~667 // bytes/second write speed on SST SST25VF064C). You can // improve this by over a couple of orders of magnitude by // writing a function to write full pages of up to 256 bytes at // a time. This is implemented this way only because I don't // have an SST25VF064C handy to test with right now. -HS while(wLen--) SPIFlashWrite(*vData++); return; } // Activate the chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Issue WRITE_xxx_STREAM command with address SPIFLASH_SSPBUF = vOpcode; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[2]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[1]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[0]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; isStarted = TRUE; } // Otherwise, just write the AAI command again else { // Assert the chip select pin SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Issue the WRITE_STREAM command for continuation SPIFLASH_SSPBUF = vOpcode; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; } // Write a byte or two for(i = 0; i <= deviceCaps.bits.bWriteWordStream; i++) { SPIFLASH_SSPBUF = *vData++; dwWriteAddr++; wLen--; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; } // Release the chip select to begin the write SPIFLASH_CS_IO = 1; // If a boundary was reached, end the write if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0) { _WaitWhileBusy(); _SendCmd(WRDI); isStarted = FALSE; } } // Wait for write to complete, then exit AAI mode _WaitWhileBusy(); _SendCmd(WRDI); // If a byte remains, write the odd address if(wLen) SPIFlashWrite(*vData); // Restore SPI state SPI_ON_BIT = 0; SPIFLASH_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
/***************************************************************************** Function: void SPIFlashWrite(BYTE vData) Summary: Writes a byte to the SPI Flash part. Description: This function writes a byte to the SPI Flash part. If the current address pointer indicates the beginning of a 4kB sector, the entire sector will first be erased to allow writes to proceed. If the current address pointer indicates elsewhere, it will be assumed that the sector has already been erased. If this is not true, the chip will silently ignore the write command. Precondition: SPIFlashInit and SPIFlashBeginWrite have been called, and the current address is either the front of a 4kB sector or has already been erased. Parameters: vData - The byte to write to the next memory location. Returns: None Remarks: See Remarks in SPIFlashBeginWrite for important information about Flash memory parts. ***************************************************************************/ void SPIFlashWrite(BYTE vData) { volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif // Save SPI state (clock speed) SPICON1Save = SPIFLASH_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIFLASH_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // If address is a boundary, erase a sector first if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0u) SPIFlashEraseSector(dwWriteAddr); // Enable writing _SendCmd(WREN); // Activate the chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Issue WRITE command with address SPIFLASH_SSPBUF = WRITE; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[2]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[1]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[0]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; // Write the byte SPIFLASH_SSPBUF = vData; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; dwWriteAddr++; // Deactivate chip select and wait for write to complete SPIFLASH_CS_IO = 1; _WaitWhileBusy(); // Restore SPI state SPI_ON_BIT = 0; SPIFLASH_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
/***************************************************************************** Function: void SPIFlashInit(void) Description: Initializes SPI Flash module. Precondition: None Parameters: None Returns: None Remarks: This function is only called once during the lifetime of the application. Internal: This function sends WRDI to clear any pending write operation, and also clears the software write-protect on all memory locations. ***************************************************************************/ void SPIFlashInit(void) { BYTE i; volatile BYTE Dummy; BYTE vSPIONSave; #if defined(__18CXX) BYTE SPICON1Save; #elif defined(__C30__) WORD SPICON1Save; #else DWORD SPICON1Save; #endif SPIFLASH_CS_IO = 1; SPIFLASH_CS_TRIS = 0; // Drive SPI Flash chip select pin SPIFLASH_SCK_TRIS = 0; // Set SCK pin as an output SPIFLASH_SDI_TRIS = 1; // Make sure SDI pin is an input SPIFLASH_SDO_TRIS = 0; // Set SDO pin as an output // Save SPI state (clock speed) SPICON1Save = SPIFLASH_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIFLASH_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; ClearSPIDoneFlag(); #if defined(__C30__) SPIFLASH_SPICON2 = 0; SPIFLASH_SPISTAT = 0; // clear SPI SPIFLASH_SPISTATbits.SPIEN = 1; #elif defined(__C32__) SPIFLASH_SPIBRG = (GetPeripheralClock()-1ul)/2ul/SPIFLASH_MAX_SPI_FREQ; #elif defined(__18CXX) SPIFLASH_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock SPIFLASH_SPISTATbits.SMP = 0; // Input sampled at middle of data output time #endif // Read Device ID code to determine supported device capabilities/instructions { // Activate chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Send instruction SPIFLASH_SSPBUF = RDID; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; // Send 3 byte address (0x000000), discard Manufacture ID, get Device ID for(i = 0; i < 5; i++) { SPIFLASH_SSPBUF = 0x00; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; } // Deactivate chip select SPIFLASH_CS_IO = 1; // Decode Device Capabilities Flags from Device ID deviceCaps.v = 0x00; switch(Dummy) { case 0x43: // SST25LF020(A) (2 Mbit) 0xAF, 14us, AAI Byte case 0x48: // SST25VF512(A) (512 Kbit) 0xAF, 14us, AAI Byte case 0x49: // SST25VF010A (1 Mbit) 0xAF, 14us, AAI Byte deviceCaps.bits.bWriteByteStream = 1; break; case 0x4B: // SST25VF064C (64 Mbit) 0x02, 1.5ms/256 byte page, no AAI deviceCaps.bits.bPageProgram = 1; break; //case 0x01: // SST25WF512 (512 Kbit) 0xAD, 50us, AAI Word //case 0x02: // SST25WF010 (1 Mbit) 0xAD, 50us, AAI Word //case 0x03: // SST25WF020 (2 Mbit) 0xAD, 50us, AAI Word //case 0x04: // SST25WF040 (4 Mbit) 0xAD, 50us, AAI Word //case 0x05: // SST25WF080 (8 Mbit) 0xAD, 14us, AAI Word //case 0x41: // SST25VF016B (16 Mbit) 0xAD, 7us, AAI Word //case 0x4A: // SST25VF032B (32 Mbit) 0xAD, 7us, AAI Word //case 0x8C: // SST25VF020B (2 Mbit) 0xAD, 7us, AAI Word //case 0x8D: // SST25VF040B (4 Mbit) 0xAD, 7us, AAI Word //case 0x8E: // SST25VF080B (8 Mbit) 0xAD, 7us, AAI Word // Assume AAI Word programming is supported for the above commented // devices and unknown devices. default: deviceCaps.bits.bWriteWordStream = 1; } } // Clear any pre-existing AAI write mode // This may occur if the PIC is reset during a write, but the Flash is // not tied to the same hardware reset. _SendCmd(WRDI); // Execute Enable-Write-Status-Register (EWSR) instruction _SendCmd(EWSR); // Clear Write-Protect on all memory locations SPIFLASH_CS_IO = 0; SPIFLASH_SSPBUF = WRSR; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = 0x00; // Clear all block protect bits WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_CS_IO = 1; // Restore SPI state SPI_ON_BIT = 0; SPIFLASH_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }
/***************************************************************************** * FUNCTION: zgHALSpiTxRx * * RETURNS: True is successful, else False * * PARAMS: None * * NOTES: SPI Tx/Rx mechansim between Host CPU and ZG2100. *****************************************************************************/ tZGBool zgHALSpiTxRx(tZGVoidInput) { #if defined(__18CXX) volatile tZGU8 dummy; #endif tZGU16 numRxPreambleBytes, numTxPreambleBytes; tZGU16 numRxDataBytes, numTxDataBytes; tZGU16 totalNumBytes; tZGU8 *p_txPreBuf, *p_rxPreBuf; tZGU8 *p_txDataBuf, *p_rxDataBuf; tZGU8 ROM *p_txDataRomBuf; tZGU8 romFlag; tZGU8 rxTrash; numRxPreambleBytes = SPICXT.rxPreambleLength; numTxPreambleBytes = SPICXT.txPreambleLength; numRxDataBytes = SPICXT.rxBufferLength + SPICXT.excessRxLength; numTxDataBytes = SPICXT.txLength; p_rxPreBuf = SPICXT.pRxPreambleBuffer; p_txPreBuf = SPICXT.pTxPreambleBuffer; p_txDataBuf = SPICXT.pTxBuffer; p_txDataRomBuf = SPICXT.pTxRomBuffer; p_rxDataBuf = SPICXT.pRxBuffer; // if more tx bytes than rx bytes, or the same count for both if ( (numTxPreambleBytes + numTxDataBytes) >= (numRxPreambleBytes + numRxDataBytes) ) { totalNumBytes = numTxPreambleBytes + numTxDataBytes; } // else more rx bytes than tx bytes else { totalNumBytes = numRxPreambleBytes + numRxDataBytes; } // if any tx data if (numTxDataBytes > 0u) { // if using tx RAM buffer if (SPICXT.pTxBuffer != 0u) { romFlag = kZGBoolFalse; } else if (SPICXT.pTxRomBuffer != 0u) { romFlag = kZGBoolTrue; } else { ZGSYS_DRIVER_ASSERT(5, (ROM char *)"SpiTxRx: Invalid Tx pointer.\n"); } } spiSuppressDoneHandlerCall = SPICXT.suppressDoneHandlerCall; SPICXT.suppressDoneHandlerCall = FALSE; // set back to default state of false, only raw txrx will set true #ifndef DEDICATED_SPI_ZG // Save SPI context so we can restore it to function entry state at end of this function SaveSpiContext(); /*---------------------------------------------*/ /* Configure SPI I/O for ZG2100 communications */ /*---------------------------------------------*/ /* enable the SPI clocks */ /* set as master */ /* clock idles high */ /* ms bit first */ /* 8 bit tranfer length */ /* data changes on falling edge */ /* data is sampled on rising edge */ /* set the clock divider */ // Set up SPI #if defined(__18CXX) ZG_SPICON1 = 0x30; // SSPEN bit is set, SPI in master mode, (0x30 is for FOSC/4), // IDLE state is high level (0x32 is for FOSC/64) ZG_SPISTATbits.CKE = 0; // Transmit data on falling edge of clock ZG_SPISTATbits.SMP = 1; // Input sampled at end? of data output time #elif defined(__C30__) ZG_SPICON1 = 0x027B; // Fcy Primary prescaler 1:1, secondary prescaler 2:1, CKP=1, CKE=0, SMP=1 ZG_SPICON2 = 0x0000; ZG_SPISTAT = 0x8000; // Enable the module #elif defined( __PIC32MX__ ) ZG_SPI_BRG = (GetPeripheralClock()-1ul)/2ul/ZG_MAX_SPI_FREQ; ZG_SPICON1 = 0x00000260; // sample at end, data change idle to active, clock idle high, master ZG_SPICON1bits.ON = 1; #else #error Configure SPI for the selected processor #endif #endif /* DEDICATED_SPI_ZG */ /* set SS low */ ZG_CS_IO = 0; /* clear any pending interrupts */ #if defined(__18CXX) dummy = ZG_SSPBUF; ClearSPIDoneFlag(); #endif // while Tx and/or Rx bytes left to handle while (totalNumBytes > 0u) { #if 0 { unsigned short i = 400; // 0x40; fails on PIC18 while(i--) { Nop(); Nop(); } } #endif // if still outputting tx preamble bytes if (numTxPreambleBytes > 0u) { --numTxPreambleBytes; ZG_SSPBUF = *p_txPreBuf++; } // else if still outputting tx data bytes else if (numTxDataBytes > 0u) { --numTxDataBytes; // if outputting from RAM buffer if (!romFlag) { ZG_SSPBUF = *p_txDataBuf++; } // else outputting from ROM buffer else { ZG_SSPBUF = *p_txDataRomBuf++; } } // else there were no Tx bytes to output or we are done, so just stuff an FF into SPI tx register else { ZG_SSPBUF = 0xff; } // wait until tx/rx byte completely clocked out WaitForDataByte(); // if still reading Rx preamble bytes if (numRxPreambleBytes > 0u) { --numRxPreambleBytes; *p_rxPreBuf++ = ZG_SSPBUF; } // else if still reading Rx data bytes else if (numRxDataBytes > 0u) { --numRxDataBytes; *p_rxDataBuf++ = ZG_SSPBUF; } // else done with Rx data else { // throw away rx byte rxTrash = ZG_SSPBUF; } --totalNumBytes; } // end while /* Disable the interrupt */ #if defined( __PIC32MX__ ) ZG_SPI_IE_CLEAR = ZG_SPI_INT_BITS; #else ZG_SPI_IE = 0; #endif /* set SS high */ ZG_CS_IO = 1; if ( !spiSuppressDoneHandlerCall ) { zgDriverSpiTxRxDoneHandler(); } #ifndef DEDICATED_SPI_ZG // Restore SPI I/O state to what it was when this function was entered RestoreSpiContext(); #endif return kZGBoolTrue; }
/***************************************************************************** Function: void SPIFlashReadArray(uint32_t dwAddress, uint8_t *vData, uint16_t wLength) Description: Reads an array of bytes from the SPI Flash module. Precondition: SPIFlashInit has been called, and the chip is not busy (should be handled elsewhere automatically.) Parameters: dwAddress - Address from which to read vData - Where to store data that has been read wLength - Length of data to read Returns: None ***************************************************************************/ void SPIFlashReadArray(uint32_t dwAddress, uint8_t *vData, uint16_t wLength) { volatile uint8_t Dummy; uint8_t vSPIONSave; #if defined(__C30__) uint16_t SPICON1Save; #elif defined(__C32__) uint32_t SPICON1Save; #endif // Ignore operations when the destination is NULL or nothing to read if(vData == NULL || wLength == 0) return; // Save SPI state (clock speed) SPICON1Save = SPIFLASH_SPICON1; vSPIONSave = SPI_ON_BIT; // Configure SPI SPI_ON_BIT = 0; SPIFLASH_SPICON1 = PROPER_SPICON1; SPI_ON_BIT = 1; // Activate chip select SPIFLASH_CS_IO = 0; ClearSPIDoneFlag(); // Send READ opcode SPIFLASH_SSPBUF = READ; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; // Send address SPIFLASH_SSPBUF = ((uint8_t*)&dwAddress)[2]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((uint8_t*)&dwAddress)[1]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; SPIFLASH_SSPBUF = ((uint8_t*)&dwAddress)[0]; WaitForDataByte(); Dummy = SPIFLASH_SSPBUF; // Read data while(wLength--) { SPIFLASH_SSPBUF = 0; WaitForDataByte(); *vData++ = SPIFLASH_SSPBUF; } // Deactivate chip select SPIFLASH_CS_IO = 1; // Restore SPI state SPI_ON_BIT = 0; SPIFLASH_SPICON1 = SPICON1Save; SPI_ON_BIT = vSPIONSave; }