Subversion Repositories HomeAutomation

Rev

Rev 363 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*********************************************************************
  2.  *
  3.  *               Data SPI EEPROM Access Routines
  4.  *
  5.  *********************************************************************
  6.  * FileName:        SPIEEPROM.c
  7.  * Dependencies:    Compiler.h
  8.  *                  XEEPROM.h
  9.  * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
  10.  * Complier:        Microchip C18 v3.02 or higher
  11.  *                  Microchip C30 v2.01 or higher
  12.  * Company:         Microchip Technology, Inc.
  13.  *
  14.  * Software License Agreement
  15.  *
  16.  * This software is owned by Microchip Technology Inc. ("Microchip")
  17.  * and is supplied to you for use exclusively as described in the
  18.  * associated software agreement.  This software is protected by
  19.  * software and other intellectual property laws.  Any use in
  20.  * violation of the software license may subject the user to criminal
  21.  * sanctions as well as civil liability.  Copyright 2006 Microchip
  22.  * Technology Inc.  All rights reserved.
  23.  *
  24.  * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL
  25.  * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
  26.  * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
  27.  * INFRINGEMENT.  Microchip shall in no event be liable for special,
  28.  * incidental, or consequential damages.
  29.  *
  30.  *
  31.  * Author               Date        Comment
  32.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33.  * Nilesh Rajbharti     5/20/02     Original (Rev. 1.0)
  34.  * Howard Schlunder     9/01/04     Rewritten for SPI EEPROMs
  35.  * Howard Schlunder     8/10/06     Modified to control SPI module
  36.  *                                  frequency whenever EEPROM accessed
  37.  *                                  to allow bus sharing with different
  38.  *                                  frequencies.
  39. ********************************************************************/
  40. #include "..\Include\Compiler.h"
  41. #include "..\Include\XEEPROM.h"
  42. #include "..\Include\StackTsk.h"
  43.  
  44. #if defined(MPFS_USE_EEPROM)
  45.  
  46. #if defined(PICDEMNET)
  47.     #error "PICDEMNET is defined, but the PICDEM.net demo board does not have an SPI EEPROM on it.  Is I2CEEPROM.c intended instead?"
  48. #endif
  49.  
  50.  
  51. // IMPORTANT SPI NOTE: The code in this file expects that the SPI interrupt
  52. //      flag (EEPROM_SPI_IF) be clear at all times.  If the SPI is shared with
  53. //      other hardware, the other code should clear the EEPROM_SPI_IF when it is
  54. //      done using the SPI.
  55.  
  56.  
  57. // EEPROM SPI opcodes
  58. #define READ    0b00000011  // Read data from memory array beginning at selected address
  59. #define WRITE   0b00000010  // Write data to memory array beginning at selected address
  60. #define WRDI    0b00000100  // Reset the write enable latch (disable write operations)
  61. #define WREN    0b00000110  // Set the write enable latch (enable write operations)
  62. #define RDSR    0b00000101  // Read Status register
  63. #define WRSR    0b00000001  // Write Status register
  64.  
  65. void DoWrite(void);
  66.  
  67. WORD EEPROMAddress;
  68. BYTE EEPROMBuffer[EEPROM_BUFFER_SIZE];
  69. BYTE *EEPROMBufferPtr;
  70.  
  71. /*********************************************************************
  72.  * Function:        void XEEInit(unsigned char speed)
  73.  *
  74.  * PreCondition:    None
  75.  *
  76.  * Input:           speed - not used (included for compatibility only)
  77.  *
  78.  * Output:          None
  79.  *
  80.  * Side Effects:    None
  81.  *
  82.  * Overview:        Initialize SPI module to communicate to serial
  83.  *                  EEPROM.
  84.  *
  85.  * Note:            Code sets SPI clock to Fosc/16.  
  86.  ********************************************************************/
  87. #if defined(HPC_EXPLORER) && !defined(__18F87J10)
  88.     #define PROPER_SPICON1  (0x20)      /* SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level */
  89. #elif defined(__PIC24F__)
  90.     #define PROPER_SPICON1  (0x0013 | 0x0120)   /* 1:1 primary prescale, 4:1 secondary prescale, CKE=1, MASTER mode */
  91. #elif defined(__dsPIC30F__)
  92.     #define PROPER_SPICON1  (0x0017 | 0x0120)   /* 1:1 primary prescale, 3:1 secondary prescale, CKE=1, MASTER mode */
  93. #elif defined(__dsPIC33F__) || defined(__PIC24H__)
  94.     #define PROPER_SPICON1  (0x0003 | 0x0120)   /* 1:1 primary prescale, 8:1 secondary prescale, CKE=1, MASTER mode */
  95. #else
  96.     //#define PROPER_SPICON1    (0x21)      /* SSPEN bit is set, SPI in master mode, FOSC/16, IDLE state is low level */
  97.     #define PROPER_SPICON1  (0x22)      /* SSPEN bit is set, SPI in master mode, FOSC/16, IDLE state is low level */
  98. #endif
  99.  
  100. void XEEInit(unsigned char speed)
  101. {
  102.     EEPROM_CS_IO = 1;
  103.     EEPROM_CS_TRIS = 0;     // Drive SPI EEPROM chip select pin
  104.  
  105.     EEPROM_SCK_TRIS = 0;    // Set SCK pin as an output
  106.     EEPROM_SDI_TRIS = 1;    // Make sure SDI pin is an input
  107.     EEPROM_SDO_TRIS = 0;    // Set SDO pin as an output
  108.  
  109.     EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
  110.     #if defined(__C30__)
  111.         EEPROM_SPICON2 = 0;
  112.         EEPROM_SPISTAT = 0;    // clear SPI
  113.         EEPROM_SPISTATbits.SPIEN = 1;
  114.     #elif defined(__18CXX)
  115.         EEPROM_SPI_IF = 0;
  116.         EEPROM_SPISTATbits.CKE = 1;     // Transmit data on rising edge of clock
  117.         EEPROM_SPISTATbits.SMP = 0;     // Input sampled at middle of data output time
  118.     #endif
  119. }
  120.  
  121.  
  122. /*********************************************************************
  123.  * Function:        XEE_RESULT XEEBeginRead(unsigned char control,
  124.  *                                          XEE_ADDR address)
  125.  *
  126.  * PreCondition:    XEEInit() is already called.
  127.  *
  128.  * Input:           control - EEPROM control and address code.
  129.  *                  address - Address at which read is to be performed.
  130.  *
  131.  * Output:          XEE_SUCCESS if successful
  132.  *                  other value if failed.
  133.  *
  134.  * Side Effects:    None
  135.  *
  136.  * Overview:        Sets internal address counter to given address.
  137.  *                  Puts EEPROM in sequential read mode.
  138.  *
  139.  * Note:            This function does not release I2C bus.
  140.  *                  User must call XEEEndRead() when read is not longer
  141.  *                  needed; I2C bus will released after XEEEndRead()
  142.  *                  is called.
  143.  ********************************************************************/
  144. XEE_RESULT XEEBeginRead(unsigned char control, XEE_ADDR address )
  145. {
  146.     // Save the address and emptry the contents of our local buffer
  147.     EEPROMAddress = address;
  148.     EEPROMBufferPtr = EEPROMBuffer + EEPROM_BUFFER_SIZE;
  149.     return XEE_SUCCESS;
  150. }
  151.  
  152.  
  153. /*********************************************************************
  154.  * Function:        XEE_RESULT XEERead(void)
  155.  *
  156.  * PreCondition:    XEEInit() && XEEBeginRead() are already called.
  157.  *
  158.  * Input:           None
  159.  *
  160.  * Output:          XEE_SUCCESS if successful
  161.  *                  other value if failed.
  162.  *
  163.  * Side Effects:    None
  164.  *
  165.  * Overview:        Reads next byte from EEPROM; internal address
  166.  *                  is incremented by one.
  167.  *
  168.  * Note:            This function does not release I2C bus.
  169.  *                  User must call XEEEndRead() when read is not longer
  170.  *                  needed; I2C bus will released after XEEEndRead()
  171.  *                  is called.
  172.  ********************************************************************/
  173. unsigned char XEERead(void)
  174. {
  175.     // Check if no more bytes are left in our local buffer
  176.     if( EEPROMBufferPtr == EEPROMBuffer + EEPROM_BUFFER_SIZE )
  177.     {
  178.         // Get a new set of bytes
  179.         XEEReadArray(0, EEPROMAddress, EEPROMBuffer, EEPROM_BUFFER_SIZE);
  180.         EEPROMAddress += EEPROM_BUFFER_SIZE;
  181.         EEPROMBufferPtr = EEPROMBuffer;
  182.     }
  183.  
  184.     // Return a byte from our local buffer
  185.     return *EEPROMBufferPtr++;
  186. }
  187.  
  188. /*********************************************************************
  189.  * Function:        XEE_RESULT XEEEndRead(void)
  190.  *
  191.  * PreCondition:    XEEInit() && XEEBeginRead() are already called.
  192.  *
  193.  * Input:           None
  194.  *
  195.  * Output:          XEE_SUCCESS if successful
  196.  *                  other value if failed.
  197.  *
  198.  * Side Effects:    None
  199.  *
  200.  * Overview:        Ends sequential read cycle.
  201.  *
  202.  * Note:            This function ends sequential cycle that was in
  203.  *                  progress.  It releases I2C bus.
  204.  ********************************************************************/
  205. XEE_RESULT XEEEndRead(void)
  206. {
  207.     return XEE_SUCCESS;
  208. }
  209.  
  210.  
  211. /*********************************************************************
  212.  * Function:        XEE_RESULT XEEReadArray(unsigned char control,
  213.  *                                          XEE_ADDR address,
  214.  *                                          unsigned char *buffer,
  215.  *                                          unsigned char length)
  216.  *
  217.  * PreCondition:    XEEInit() is already called.
  218.  *
  219.  * Input:           control     - Unused
  220.  *                  address     - Address from where array is to be read
  221.  *                  buffer      - Caller supplied buffer to hold the data
  222.  *                  length      - Number of bytes to read.
  223.  *
  224.  * Output:          XEE_SUCCESS if successful
  225.  *                  other value if failed.
  226.  *
  227.  * Side Effects:    None
  228.  *
  229.  * Overview:        Reads desired number of bytes in sequential mode.
  230.  *                  This function performs all necessary steps
  231.  *                  and releases the bus when finished.
  232.  *
  233.  * Note:            None
  234.  ********************************************************************/
  235. XEE_RESULT XEEReadArray(unsigned char control,
  236.                         XEE_ADDR address,
  237.                         unsigned char *buffer,
  238.                         unsigned char length)
  239. {
  240.     BYTE Dummy;
  241.     #if defined(__18CXX)
  242.     BYTE SPICON1Save;
  243.     #else
  244.     WORD SPICON1Save;
  245.     #endif 
  246.  
  247.     // Save SPI state (clock speed)
  248.     SPICON1Save = EEPROM_SPICON1;
  249.     EEPROM_SPICON1 = PROPER_SPICON1;
  250.  
  251.     EEPROM_CS_IO = 0;
  252.  
  253.     // Send READ opcode
  254.     EEPROM_SSPBUF = READ;
  255.     while(!EEPROM_SPI_IF);
  256.     Dummy = EEPROM_SSPBUF;
  257.     EEPROM_SPI_IF = 0;
  258.    
  259.     // Send address
  260.     EEPROM_SSPBUF = ((WORD_VAL*)&address)->v[1];
  261.     while(!EEPROM_SPI_IF);
  262.     Dummy = EEPROM_SSPBUF;
  263.     EEPROM_SPI_IF = 0;
  264.     EEPROM_SSPBUF = ((WORD_VAL*)&address)->v[0];
  265.     while(!EEPROM_SPI_IF);
  266.     Dummy = EEPROM_SSPBUF;
  267.     EEPROM_SPI_IF = 0;
  268.    
  269.     while(length--)
  270.     {
  271.         EEPROM_SSPBUF = 0;
  272.         while(!EEPROM_SPI_IF);
  273.         *buffer++ = EEPROM_SSPBUF;
  274.         EEPROM_SPI_IF = 0;
  275.     };
  276.    
  277.     EEPROM_CS_IO = 1;
  278.  
  279.     // Restore SPI state
  280.     EEPROM_SPICON1 = SPICON1Save;
  281.  
  282.     return XEE_SUCCESS;
  283. }
  284.  
  285.  
  286. /*********************************************************************
  287.  * Function:        XEE_RESULT XEESetAddr(unsigned char control,
  288.  *                                        XEE_ADDR address)
  289.  *
  290.  * PreCondition:    XEEInit() is already called.
  291.  *
  292.  * Input:           control     - data EEPROM control code
  293.  *                  address     - address to be set for writing
  294.  *
  295.  * Output:          XEE_SUCCESS if successful
  296.  *                  other value if failed.
  297.  *
  298.  * Side Effects:    None
  299.  *
  300.  * Overview:        Modifies internal address counter of EEPROM.
  301.  *
  302.  * Note:            Unlike XEESetAddr() in xeeprom.c for I2C EEPROM
  303.  *                   memories, this function is used only for writing
  304.  *                   to the EEPROM.  Reads must use XEEBeginRead(),
  305.  *                   XEERead(), and XEEEndRead().
  306.  *                  This function does not release the SPI bus.
  307.  *                  User must close XEEClose() after this function
  308.  *                   is called.
  309.  ********************************************************************/
  310. XEE_RESULT XEESetAddr(unsigned char control, XEE_ADDR address)
  311. {
  312.     EEPROMAddress = address;
  313.     EEPROMBufferPtr = EEPROMBuffer;
  314.     return XEE_SUCCESS;
  315. }
  316.  
  317.  
  318. /*********************************************************************
  319.  * Function:        XEE_RESULT XEEWrite(unsigned char val)
  320.  *
  321.  * PreCondition:    XEEInit() && XEEBeginWrite() are already called.
  322.  *
  323.  * Input:           val - Byte to be written
  324.  *
  325.  * Output:          XEE_SUCCESS
  326.  *
  327.  * Side Effects:    None
  328.  *
  329.  * Overview:        Adds a byte to the current page to be writen when
  330.  *                  XEEEndWrite() is called.
  331.  *
  332.  * Note:            Page boundary cannot be exceeded or the byte
  333.  *                  to be written will be looped back to the
  334.  *                  beginning of the page.
  335.  ********************************************************************/
  336. XEE_RESULT XEEWrite(unsigned char val)
  337. {
  338.     *EEPROMBufferPtr++ = val;
  339.     if( EEPROMBufferPtr == EEPROMBuffer + EEPROM_BUFFER_SIZE )
  340.     {
  341.         DoWrite();
  342.     }
  343.  
  344.     return XEE_SUCCESS;
  345. }
  346.  
  347.  
  348. /*********************************************************************
  349.  * Function:        XEE_RESULT XEEEndWrite(void)
  350.  *
  351.  * PreCondition:    XEEInit() && XEEBeginWrite() are already called.
  352.  *
  353.  * Input:           None
  354.  *
  355.  * Output:          XEE_SUCCESS if successful
  356.  *                  other value if failed.
  357.  *
  358.  * Side Effects:    None
  359.  *
  360.  * Overview:        Instructs EEPROM to begin write cycle.
  361.  *
  362.  * Note:            Call this function after either page full of bytes
  363.  *                  written or no more bytes are left to load.
  364.  *                  This function initiates the write cycle.
  365.  *                  User must call for XEEIsBusy() to ensure that write
  366.  *                  cycle is finished before calling any other
  367.  *                  routine.
  368.  ********************************************************************/
  369. XEE_RESULT XEEEndWrite(void)
  370. {
  371.     if( EEPROMBufferPtr != EEPROMBuffer )
  372.     {
  373.         DoWrite();
  374.     }
  375.  
  376.     return XEE_SUCCESS;
  377. }
  378.  
  379. void DoWrite(void)
  380. {
  381.     BYTE Dummy;
  382.     BYTE BytesToWrite;
  383.     #if defined(__18CXX)
  384.     BYTE SPICON1Save;
  385.     #else
  386.     WORD SPICON1Save;
  387.     #endif 
  388.  
  389.     // Save SPI state (clock speed)
  390.     SPICON1Save = EEPROM_SPICON1;
  391.     EEPROM_SPICON1 = PROPER_SPICON1;
  392.    
  393.     // Set the Write Enable latch
  394.     EEPROM_CS_IO = 0;
  395.     EEPROM_SSPBUF = WREN;
  396.     while(!EEPROM_SPI_IF);
  397.     Dummy = EEPROM_SSPBUF;
  398.     EEPROM_SPI_IF = 0;
  399.     EEPROM_CS_IO = 1;
  400.    
  401.     // Send WRITE opcode
  402.     EEPROM_CS_IO = 0;
  403.     EEPROM_SSPBUF = WRITE;
  404.     while(!EEPROM_SPI_IF);
  405.     Dummy = EEPROM_SSPBUF;
  406.     EEPROM_SPI_IF = 0;
  407.    
  408.     // Send address
  409.     EEPROM_SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[1];
  410.     while(!EEPROM_SPI_IF);
  411.     Dummy = EEPROM_SSPBUF;
  412.     EEPROM_SPI_IF = 0;
  413.     EEPROM_SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[0];
  414.     while(!EEPROM_SPI_IF);
  415.     Dummy = EEPROM_SSPBUF;
  416.     EEPROM_SPI_IF = 0;
  417.    
  418.     BytesToWrite = (BYTE)(EEPROMBufferPtr - EEPROMBuffer);
  419.    
  420.     EEPROMAddress += BytesToWrite;
  421.     EEPROMBufferPtr = EEPROMBuffer;
  422.  
  423.     while(BytesToWrite--)
  424.     {
  425.         // Send the byte to write
  426.         EEPROM_SSPBUF = *EEPROMBufferPtr++;
  427.         while(!EEPROM_SPI_IF);
  428.         Dummy = EEPROM_SSPBUF;
  429.         EEPROM_SPI_IF = 0;
  430.     }
  431.  
  432.     // Begin the write
  433.     EEPROM_CS_IO = 1;
  434.  
  435.     EEPROMBufferPtr = EEPROMBuffer;
  436.  
  437.     // Restore SPI State
  438.     EEPROM_SPICON1 = SPICON1Save;
  439.  
  440.     // Wait for write to complete
  441.     while( XEEIsBusy(0) );
  442. }
  443.  
  444.  
  445. /*********************************************************************
  446.  * Function:        XEE_RESULT XEEIsBusy(unsigned char control)
  447.  *
  448.  * PreCondition:    XEEInit() is already called.
  449.  *
  450.  * Input:           control     - EEPROM control and address code.
  451.  *
  452.  * Output:          XEE_READY if EEPROM is not busy
  453.  *                  XEE_BUSY if EEPROM is busy
  454.  *                  other value if failed.
  455.  *
  456.  * Side Effects:    None
  457.  *
  458.  * Overview:        Requests ack from EEPROM.
  459.  *
  460.  * Note:            None
  461.  ********************************************************************/
  462. XEE_RESULT XEEIsBusy(unsigned char control)
  463. {
  464.     BYTE_VAL result;
  465.     #if defined(__18CXX)
  466.     BYTE SPICON1Save;
  467.     #else
  468.     WORD SPICON1Save;
  469.     #endif 
  470.  
  471.     // Save SPI state (clock speed)
  472.     SPICON1Save = EEPROM_SPICON1;
  473.     EEPROM_SPICON1 = PROPER_SPICON1;
  474.  
  475.     EEPROM_CS_IO = 0;
  476.     // Send RDSR - Read Status Register opcode
  477.     EEPROM_SSPBUF = RDSR;
  478.     while(!EEPROM_SPI_IF);
  479.     result.Val = EEPROM_SSPBUF;
  480.     EEPROM_SPI_IF = 0;
  481.    
  482.     // Get register contents
  483.     EEPROM_SSPBUF = 0;
  484.     while(!EEPROM_SPI_IF);
  485.     result.Val = EEPROM_SSPBUF;
  486.     EEPROM_SPI_IF = 0;
  487.     EEPROM_CS_IO = 1;
  488.  
  489.     // Restore SPI State
  490.     EEPROM_SPICON1 = SPICON1Save;
  491.  
  492.     return result.bits.b0 ? XEE_BUSY : XEE_SUCCESS;
  493. }
  494.  
  495.  
  496. #endif //#if defined(MPFS_USE_EEPROM)
  497.