예제 #1
0
/*********************************************************************
 * 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;
    DWORD SPICON1Save;


    // Save SPI state
    SPICON1Save = EEPROM_SPICON1;
    vSPIONSave = SPI_ON_BIT;

    // Configure SPI
    SPI_ON_BIT = 0;
    EEPROM_SPICON1 = PROPER_SPICON1;
    SPI_ON_BIT = 1;

    EEPROM_CS_IO = 0;
    // 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;
    EEPROM_CS_IO = 1;

    // Restore SPI State
    SPI_ON_BIT = 0;
    EEPROM_SPICON1 = SPICON1Save;
    SPI_ON_BIT = vSPIONSave;

    return result.bits.b0;
}
예제 #2
0
/*********************************************************************
 * 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;
    DWORD SPICON1Save;


    // 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;

    EEPROM_CS_IO = 0;

    // 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;
    };

    EEPROM_CS_IO = 1;

    // Restore SPI state
    SPI_ON_BIT = 0;
    EEPROM_SPICON1 = SPICON1Save;
    SPI_ON_BIT = vSPIONSave;


    return XEE_SUCCESS;
}
예제 #3
0
/*****************************************************************************
  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;
}
예제 #4
0
파일: SPIRAM.c 프로젝트: AleSuky/SkP32v1.1
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;
}
예제 #5
0
/*****************************************************************************
  Function:
	void WFSpiTxRx(void)

  Summary:
	Transmits and receives SPI bytes

  Description:
	Transmits and receives N bytes of SPI data.

  Precondition:
	None

  Parameters:
	p_txBuf - pointer to SPI tx data
	txLen   - number of bytes to Tx
	p_rxBuf - pointer to where SPI rx data will be stored
	rxLen   - number of SPI rx bytes caller wants copied to p_rxBuf

  Returns:
  	None
  	
  Remarks:
	Will clock out the larger of txLen or rxLen, and pad if necessary.
*****************************************************************************/
void WFSpiTxRx(UINT8   *p_txBuf, 
               UINT16  txLen, 
               UINT8   *p_rxBuf,
               UINT16  rxLen)
{
    #if defined(__18CXX)    
        static UINT16 byteCount;  /* avoid local variables in functions called from interrupt routine */
        static UINT16 i;
        static UINT8  rxTrash;
    #else
        UINT16 byteCount;
        UINT16 i;
        UINT8  rxTrash;
    #endif    


#ifdef WF_DEBUG
    /* Cannot communicate with MRF24WB0M when it is in hibernate mode */
    {
        static UINT8 state;  /* avoid local vars in functions called from interrupt */
        WF_GetPowerSaveState(&state);
        WF_ASSERT(state != WF_PS_HIBERNATE);
    }    
#endif 
    
    /* total number of byte to clock is whichever is larger, txLen or rxLen */
    byteCount = (txLen >= rxLen)?txLen:rxLen;
    
    for (i = 0; i < byteCount; ++i)
    {
        /* if still have bytes to transmit from tx buffer */
        if (txLen > 0)
        {
            WF_SSPBUF = *p_txBuf++;
            --txLen;
        }
        /* else done writing bytes out from tx buffer */
        else
        {
            WF_SSPBUF = 0xff;  /* clock out a "don't care" byte */
        }  

        /* wait until tx/rx byte to completely clock out */
        WaitForDataByte();
        
        /* if still have bytes to read into rx buffer */
        if (rxLen > 0)
        {
            *p_rxBuf++ = WF_SSPBUF;
            --rxLen;
        }
        /* else done reading bytes into rx buffer */ 
        else
        {
            rxTrash = WF_SSPBUF;  /* read and throw away byte */
        }    
    }  /* end for loop */  
    
}                      
예제 #6
0
unsigned char dog_spi_out(unsigned char data)
{
  		volatile uint8_t vDummy;
		LCD_SSPBUF=data;
		//     while (LCD_SPISTATbits.SPITBF == 1);
		WaitForDataByte();
		//LCD_SPI_IF=0;
		vDummy = LCD_SSPBUF;

}
예제 #7
0
/*********************************************************************
 * 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;
}
예제 #8
0
// Function: writeByteSpi(char b)
// Description: sends one byte (b) to the slave spi device and reads one byte at the same time.
// Return: the byte read simultaneously.
char writeByteSpi(char b)
{
	unsigned int i;
	WIFI_CS_IO = 0;		// assert the WiFi board
	WIFI_SSPBUF = b;	// write byte to be sent during exchange
	WaitForDataByte();	// wait for exchange to complete.
	WIFI_CS_IO = 1;		// deassert the WiFi board
	// pause before sending the next byte
	for (i = 0; i < 300; i++);
	return WIFI_SSPBUF;	// return the byte that was received during the exchange
}	
예제 #9
0
/*********************************************************************
 * 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 TCPIP_UINT8_VAL result;
    uint8_t vSPIONSave;
#if defined(__XC8)
    uint8_t SPICON1Save;
#elif defined(__XC16)
    uint16_t SPICON1Save;
#else
    uint32_t 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;

    EEPROM_CS_IO = 0;
    // 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;
    EEPROM_CS_IO = 1;

    // Restore SPI State
    SPI_ON_BIT = 0;
    EEPROM_SPICON1 = SPICON1Save;
    SPI_ON_BIT = vSPIONSave;

    return result.bits.b0;
}
예제 #10
0
/*****************************************************************************
  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;
}
예제 #11
0
/*****************************************************************************
  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;
}
예제 #12
0
/*****************************************************************************
  Function:
	void WFSpiTxRx_Rom(void)

  Summary:
	Transmits and receives SPI bytes

  Description:
	Specific to the PIC18, transmits bytes from ROM storage and receives SPI data 
	bytes.

  Precondition:
	None

  Parameters:
	p_txBuf - pointer to SPI ROM tx data
	txLen   - number of bytes to Tx
	p_rxBuf - pointer to where SPI rx data will be stored
	rxLen   - number of SPI rx bytes caller wants copied to p_rxBuf

  Returns:
  	None
  	
  Remarks:
	Will clock out the larger of txLen or rxLen, and pad if necessary.
*****************************************************************************/
void WFSpiTxRx_Rom(ROM UINT8 *p_txBuf, 
                     UINT16    txLen, 
                     UINT8     *p_rxBuf,
                     UINT16    rxLen)
{
        static UINT16 byteCount;  /* avoid local variables in functions called from interrupt routine */
        static UINT16 i;
        static UINT8  rxTrash;

    /* total number of byte to clock is whichever is larger, txLen or rxLen */
    byteCount = (txLen >= rxLen)?txLen:rxLen;
    
    for (i = 0; i < byteCount; ++i)
    {
        /* if still have bytes to transmit from tx buffer */
        if (txLen > 0)
        {
            WF_SSPBUF = *p_txBuf++;
            --txLen;
        }
        /* else done writing bytes out from tx buffer */
        else
        {
            WF_SSPBUF = 0xff;  /* clock out a "don't care" byte */
        }  

        // wait until tx/rx byte completely clocked out
        WaitForDataByte();
        
        /* if still have bytes to read into rx buffer */
        if (rxLen > 0)
        {
            *p_rxBuf++ = WF_SSPBUF;
            --rxLen;
        }
        /* else done reading bytes into rx buffer */ 
        else
        {
            rxTrash = WF_SSPBUF;  /* read and throw away byte */
        }    
    }  /* end for loop */  
}    
예제 #13
0
static void DoWrite(void)
{
    BYTE i;
    volatile BYTE vDummy;
    BYTE vSPIONSave;
    DWORD SPICON1Save;


    // 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
    EEPROM_CS_IO = 0;
    EEPROM_SSPBUF = OPCODE_WREN;
    WaitForDataByte();
    vDummy = EEPROM_SSPBUF;
    EEPROM_CS_IO = 1;

    // Send WRITE opcode
    EEPROM_CS_IO = 0;
    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
    EEPROM_CS_IO = 1;

	// 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() );
}
예제 #14
0
/*****************************************************************************
  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;
}
예제 #15
0
/*****************************************************************************
  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;
}
예제 #16
0
/*****************************************************************************
  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;
}
예제 #17
0
/*****************************************************************************
  Function:
	void DRV_SPI_TxRx(void)

  Summary:
	Transmits and receives SPI bytes

  Description:
	Transmits and receives N bytes of SPI data.

  Precondition:
	None

  Parameters:
	pTxBuf - pointer to SPI tx data
	txLen   - number of bytes to Tx
	pRxBuf - pointer to where SPI rx data will be stored
	rxLen   - number of SPI rx bytes caller wants copied to p_rxBuf

  Returns:
  	None
  	
  Remarks:
	Will clock out the larger of txLen or rxLen, and pad if necessary.
*****************************************************************************/
void DRV_SPI_TxRx(SpiChannel chn,
			   uint8_t   *pTxBuf, 
               uint16_t  txLen, 
               uint8_t   *pRxBuf,
               uint16_t  rxLen)
{
	uint16_t byteCount;
	uint16_t i;
	uint8_t  rxTrash;

    /* total number of byte to clock is whichever is larger, txLen or rxLen */
    byteCount = (txLen >= rxLen)?txLen:rxLen;
    
    for (i = 0; i < byteCount; ++i)
    {
        /* if still have bytes to transmit from tx buffer */
        if ((txLen > 0) && (pTxBuf != 0))
        {
			#if defined (__C32__)
            	SpiChnWriteC(chn, *pTxBuf++);
			#elif defined (__C30__)
				switch(chn)
				{
					case 1:
						WriteSPI1(*pTxBuf++);
						break;
					case 2:
						WriteSPI2(*pTxBuf++);
						break;
				}
			#endif
            --txLen;
        }
        /* else done writing bytes out from tx buffer */
        else
        { 
			#if defined (__C32__)

	            SpiChnWriteC(chn, 0); /* clock out a "don't care" byte */
			#elif defined (__C30__)

				switch(chn)
				{
					case 1:
						WriteSPI1(0x00);
						break;
					case 2:
						WriteSPI2(0x00);
						break;
				}
			#endif	
        }  

        /* wait until tx/rx byte to completely clock out */
        WaitForDataByte(chn);
        
        /* if still have bytes to read into rx buffer */
        if ((rxLen > 0) && (pRxBuf != 0))
        {
			#if defined (__C32__)

	            *pRxBuf++ = SpiChnReadC(chn);
			#elif defined (__C30__)

				switch(chn)
				{
					case 1:
						*pRxBuf++ = ReadSPI1();
						break;
					case 2:
						*pRxBuf++ = ReadSPI2();
						break;

				}
			#endif
            --rxLen;
        }
        /* else done reading bytes into rx buffer */ 
        else
        {
			#if defined (__C32__)

	            rxTrash = SpiChnReadC(chn); /* read and throw away byte */
			#elif defined (__C30__)

				switch(chn)
				{
					case 1:
						rxTrash = ReadSPI1();
						break;
					case 2:
						rxTrash = ReadSPI2();
						break;

				}
			#endif
        }    
    }  /* end for loop */  
}
예제 #18
0
파일: SPIRAM.c 프로젝트: AleSuky/SkP32v1.1
/*********************************************************************
 * 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;
}
예제 #19
0
파일: SPIRAM.c 프로젝트: AleSuky/SkP32v1.1
/*********************************************************************
 * 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;
}
예제 #20
0
/*********************************************************************
 * Function:        XEE_RESULT XEEReadArray(uint32_t address,
 *                                          uint8_t *buffer,
 *                                          uint16_t 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(uint32_t address,
        uint8_t *buffer,
        uint16_t length)
{
    volatile uint8_t Dummy;
    uint8_t vSPIONSave;
#if defined(__XC8)
    uint8_t SPICON1Save;
#elif defined(__XC16)
    uint16_t SPICON1Save;
#else
    uint32_t 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;

    EEPROM_CS_IO = 0;

    // Send READ opcode
    EEPROM_SSPBUF = OPCODE_READ;
    WaitForDataByte();
    Dummy = EEPROM_SSPBUF;

    // Send address
#if defined(USE_EEPROM_25LC1024)
    EEPROM_SSPBUF = ((TCPIP_UINT32_VAL *) & address)->v[2];
    WaitForDataByte();
    Dummy = EEPROM_SSPBUF;
#endif

    EEPROM_SSPBUF = ((TCPIP_UINT32_VAL *) & address)->v[1];
    WaitForDataByte();
    Dummy = EEPROM_SSPBUF;

    EEPROM_SSPBUF = ((TCPIP_UINT32_VAL *) & address)->v[0];
    WaitForDataByte();
    Dummy = EEPROM_SSPBUF;

    while (length--) {
        EEPROM_SSPBUF = 0;
        WaitForDataByte();
        Dummy = EEPROM_SSPBUF;
        if (buffer != NULL)
            *buffer++ = Dummy;
    };

    EEPROM_CS_IO = 1;

    // Restore SPI state
    SPI_ON_BIT = 0;
    EEPROM_SPICON1 = SPICON1Save;
    SPI_ON_BIT = vSPIONSave;

    return XEE_SUCCESS;
}
예제 #21
0
static void DoWrite(void)
{
    uint8_t i;
    uint8_t vSPIONSave;
#if defined(__XC8)
    uint8_t SPICON1Save;
#elif defined(__XC16)
    uint16_t SPICON1Save;
#else
    uint32_t 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
    EEPROM_CS_IO = 0;
    EEPROM_SSPBUF = OPCODE_WREN;
    WaitForDataByte();
    EEPROM_SSPBUF;
    EEPROM_CS_IO = 1;

    // Send WRITE opcode
    EEPROM_CS_IO = 0;
    EEPROM_SSPBUF = OPCODE_WRITE;
    WaitForDataByte();
    EEPROM_SSPBUF;

    // Send address
#if defined(USE_EEPROM_25LC1024)
    EEPROM_SSPBUF = ((TCPIP_UINT32_VAL*) & EEPROMAddress)->v[2];
    WaitForDataByte();
    EEPROM_SSPBUF;
#endif

    EEPROM_SSPBUF = ((TCPIP_UINT32_VAL*) & EEPROMAddress)->v[1];
    WaitForDataByte();
    EEPROM_SSPBUF;

    EEPROM_SSPBUF = ((TCPIP_UINT32_VAL*) & EEPROMAddress)->v[0];
    WaitForDataByte();
    EEPROM_SSPBUF;

    for (i = 0; i < vBytesInBuffer; i++) {
        // Send the byte to write
        EEPROM_SSPBUF = EEPROMBuffer[i];
        WaitForDataByte();
        EEPROM_SSPBUF;
    }

    // Begin the write
    EEPROM_CS_IO = 1;

    // 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());
}
예제 #22
0
/*****************************************************************************
 * 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;
}
예제 #23
0
/*****************************************************************************
  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;
}