/****** implementation File for support of STFL-I based Serial Flash Memory Driver ***** Filename: Serialize.c Description: Support to c2076.c. This files is aimed at giving a basic example of the SPI serial interface used to communicate with STMicroelectronics serial Flash devices. The functions below are used in an environment where the master has an embedded SPI port (STMicroelectronics µPSD). Version: 1.0 Date: 08-11-2004 Authors: Tan Zhi, STMicroelectronics, Shanghai (China) Copyright (c) 2004 STMicroelectronics. THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. ******************************************************************************** Version History. Ver. Date Comments 1.0 08/11/2004 Initial release *******************************************************************************/ #include "Serialize.h" /** uPSD specific includes #include ".\uPSD\uPSD3300.h" #include ".\uPSD\TurboLite_hardware.h" #include ".\uPSD\Turbo_timer.h" #include ".\uPSD\Turbo_SPI.h" **/ /******************************************************************************* Function: InitSPIMaster(void) Arguments: Return Values:There is no return value for this function. Description: This function is a one-time configuration for the CPU to set some ports to work in SPI mode (when they have multiple functions. For example, in some CPUs, the ports can be GPIO pins or SPI pins if properly configured). please refer to the specific CPU datasheet for proper configurations. *******************************************************************************/ void InitSPIMaster(void) { /* P4SFS0 |= 0x70; P4SFS1 |= 0x70; // Setup P4[4..6] Port as SPI // P4.7 works in GPIO mode as the Slave Select signal SPICON1=0x00; //bit3:TEIE=0. SPI transmission end interrupt disable //bit2:RORIE=0. SPI receive overrun interrupt disable //bit1:TIE=0. SPI transmission interrupt disable //bit0:RIE=0 SPI reception interrupt disable SPICLKD=0x2C; //select frequency divider=0x2C SPICON0=0x72; //bit6:TE=1. SPI Transmitter enable //bit5:RE=1. SPI Receiver enable //bit4:SPIEN=1. SPI enable //bit3:SSEL=0. SPI Slave select output is disabled,use P4.7 as the Select Slave signal //bit2:FLSB=0. SPI Transfer the MSB first //bit1:SPO=1. SPI Sample data on the rising edge of the clock */ } /******************************************************************************* Function: ConfigureSpiMaster(SpiMasterConfigOptions opt) Arguments: opt configuration options, all acceptable values are enumerated in SpiMasterConfigOptions, which is a typedefed enum. Return Values:There is no return value for this function. Description: This function can be used to properly configure the SPI master before and after the transfer/receive operation Pseudo Code: Step 1 : perform or skip select/deselect slave Step 2 : perform or skip enable/disable transfer Step 3 : perform or skip enable/disable receive *******************************************************************************/ void ConfigureSpiMaster(SpiMasterConfigOptions opt) { /* if(enumNull == opt) return; if(opt & MaskBit_SelectSlave_Relevant) (opt & MaskBit_SlaveSelect) ? SelectSlave() : DeSelectSlave(); if(opt & MaskBit_Trans_Relevant)(opt & MaskBit_Trans) ? EnableTrans():DisableTrans(); if(opt & MaskBit_Recv_Relevant) (opt & MaskBit_Recv) ? EnableRcv():DisableRcv(); */ } /******************************************************************************* Function: Serialize(const CharStream* char_stream_send, CharStream* char_stream_recv, SpiMasterConfigOptions optBefore, SpiMasterConfigOptions optAfter ) Arguments: char_stream_send, the char stream to be sent from the SPI master to the Flash memory, usually contains instruction, address, and data to be programmed. char_stream_recv, the char stream to be received from the Flash memory to the SPI master, usually contains data to be read from the memory. optBefore, configurations of the SPI master before any transfer/receive optAfter, configurations of the SPI after any transfer/receive Return Values:TRUE Description: This function can be used to encapsulate a complete transfer/receive operation Pseudo Code: Step 1 : perform pre-transfer configuration Step 2 : perform transfer/ receive Step 2-1: transfer ... (a typical process, it may vary with the specific CPU) Step 2-1-1: check until the SPI master is available Step 2-1-2: send the byte stream cycle after cycle. it usually involves: a) checking until the transfer-data-register is ready b) filling the register with a new byte Step 2-2: receive ... (a typical process, it may vary with the specific CPU) Step 2-2-1: Execute ONE pre-read cycle to clear the receive-data-register. Step 2-2-2: receive the byte stream cycle after cycle. it usually involves: a) triggering a dummy cycle b) checking until the transfer-data-register is ready(full) c) reading the transfer-data-register Step 3 : perform post-transfer configuration *******************************************************************************/ Bool Serialize(const CharStream* char_stream_send, CharStream* char_stream_recv, SpiMasterConfigOptions optBefore, SpiMasterConfigOptions optAfter ) { /* ST_uint32 i; ST_uint32 length; unsigned char* pChar; // Step 1 : perform pre-transfer configuration ConfigureSpiMaster(optBefore); // Step 2 : perform transfer / receive // Step 2-1: transfer ... length = char_stream_send->length; pChar = char_stream_send->pChar; // 2-1-1 Wait until SPI is available while (SPISTAT & SPI_FLAG_BUSY); // 2-1-2 send the byte stream cycle after cycle for(i = 0; i < length; ++i) { while (!(SPISTAT & SPI_FLAG_TI)); // check until the transfer-data-register is ready(not full) SPITDR = *(pChar++); // fill the register with a new byte } while (!(SPISTAT & SPI_FLAG_TRANSMIT_END)); // Step 2-2: receive ... // Step 2-2-1: execute ONE pre-read cycle to clear the receive-data-register. i = SPIRDR; // Step 2-2-2: send the byte stream cycle after cycle. if(ptrNull != (int)char_stream_recv) // skip if no reception needed { length = char_stream_recv->length; pChar = char_stream_recv->pChar; for(i = 0; i < length; ++i) { SPITDR = SPI_FLASH_INS_DUMMY; // triggering a dummy cycle while (!(SPISTAT & SPI_FLAG_TI)); while (!(SPISTAT & SPI_FLAG_TRANSMIT_END)); // checking until the transfer-data-register is ready while (!(SPISTAT & SPI_FLAG_RI)); *(pChar++) = SPIRDR; // read the transfer-data-register } while (!(SPISTAT & SPI_FLAG_TRANSMIT_END)); } // Step 3 : perform post-transfer configuration ConfigureSpiMaster(optAfter); */ return TRUE; }