View previous topic :: View next topic |
Author |
Message |
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
driver for SPI FRAM CY15B104Q |
Posted: Thu Oct 17, 2019 2:03 pm |
|
|
Hi,
Do you know if drivers library provided with ccsinfo contain driver compatible with SPI FRAM CY15B104Q.
If not I will write my own and share with you.
Thank you and Kind Regards
micro_debugger |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Oct 17, 2019 2:18 pm |
|
|
Normally FRAM's are reverse compatible with equivalent SPI EEPROM
drivers. I've used several without problems. However the issue here will
be there is not a 4Mbit SPI EEPROM driver in the library. The existing
1MBit driver will need to simply have the size increased, and a couple
of extra bits of address output. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 17, 2019 2:41 pm |
|
|
Thank you !
You are faster than light
When finished it will share. |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Oct 18, 2019 1:41 am |
|
|
OK. Sat down this morning and modified an SPI EEPROM driver. Think this
should be very close to right (but untested, not even compiled). If it works
we can transfer it to the code library.
Code: |
//Base attempt at a CY15B104Q FRAM driver
#ifndef __CY15B104Q__ //ensure only loads once
#define __CY15B104Q__
#include <stdint.h>
#ifndef FRAM_SELECT_PIN
#define FRAM_SELECT_PIN PIN_B4
#endif
#ifndef FRAM_CLK_PIN
#define FRAM_CLK_PIN PIN_C3
#endif
#ifndef FRAM_SDI_PIN
#define FRAM_SDI_PIN PIN_A4 //MOSI
#endif
#ifndef FRAM_SDO_PIN
#define FRAM_SDO_PIN PIN_A9 //MISO
#endif
#ifndef FRAM_SIZE
#define FRAM_SIZE 524288 //4Mbit 500Kbytes
#endif
#ifndef FRAM_SPI_BAUD
#define FRAM_SPI_BAUD 16000000 //16 MHz
#endif
//Optionally, write protect and hold pins can also be defined.
#ifndef FRAM_STREAM
#use spi(MASTER, MODE=0, CLK=FRAM_CLK_PIN, DO=FRAM_SDI_PIN, DI=FRAM_SDO_PIN, BITS=8, BAUD=FRAM_SPI_BAUD, STREAM=FRAM_STREAM)
#define FRAM_xfer(x) spi_xfer(FRAM_STREAM, x)
#else
//Handle where somebody has called with an already defined stream
//ensure transfers are byte sized.
#define FRAM_xfer(x) spi_xfer(FRAM_STREAM, x, 8)
#endif
///////////////////////////////////////////////////////////////////////////////
typedef uint32_t FRAM_ADDRESS;
//Command list
typedef enum
{
FRAM_CMD_WRSR=0x01,
FRAM_CMD_WRITE,
FRAM_CMD_READ,
FRAM_CMD_WRDI,
FRAM_CMD_RDSR,
FRAM_CMD_WREN,
FRAM_CMS_FSTRD=0xB,
FRAM_CMD_SLEEP=0xB9,
FRAM_CMD_RDID=0x9F
} FRAM_CMD;
typedef struct
{
uint8_t ManufactureCode; //should be 0x80
uint8_t FamDenCode; //should be 0x26
uint8_t[7] ManID; //should be 0x7F7F7F7F7F7FC2 - ID is 0xC2 rest fillers
} FRAM_ID;
////////////////////////////////// Prototypes /////////////////////////////////
void init_ext_FRAM(void);
uint8_t read_ext_FRAM(FRAM_ADDRESS Address);
void write_ext_FRAM(FRAM_ADDRESS Address, uint8_t Data);
void ext_FRAM_read_id(FRAM_ID *Id);
void ext_FRAM_write_enable(int1 Enable=TRUE);
void read_block_FRAM(FRAM_ADDRESS Address, BYTE * buffer, uint16_t count);
///////////////////////////////////// API /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// init_ext_FRAM()
//
// Initializes the external FRAM's chip select, hold and write protect pins.
// Should be called before any other external FRAM functions are called.
// Also ensure block protection not enabled
//
// Parameters - None.
//
// Returns - Nothing.
///////////////////////////////////////////////////////////////////////////////
void init_ext_FRAM(void)
{
output_high(FRAM_SELECT_PIN);
output_drive(FRAM_SELECT_PIN);
#ifdef FRAM_HOLD_PIN //optonal pins.
output_high(FRAM_HOLD_PIN);
output_drive(FRAM_HOLD_PIN);
#endif
#ifdef FRAM_WRITE_PROTECT_PIN
output_high(FRAM_WRITE_PROTECT_PIN);
output_drive(FRAM_WRITE_PROTECT_PIN);
#endif
ext_FRAM_write_enable(TRUE); //needs to be set before accessing the SR
//Now this chip support block protection as well as the WREN bit
//disable this for simplicity
output_low(FRAM_SELECT_PIN);
FRAM_xfer(FRAM_CMD_WRSR);
FRAM_xfer(0); //turn off protected address range
output_high(FRAM_SELECT_PIN);
ext_FRAM_write_enable(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
// read_ext_FRAM()
//
// Reads a byte from the external FRAM from the specified address.
//
// Parameters:
// Address - the address within the external FRAM to read.
//
// Returns:
// uint8_t - the byte read from the external FRAM or 0x00 if Address
// was invalid.
///////////////////////////////////////////////////////////////////////////////
uint8_t read_ext_FRAM(FRAM_ADDRESS Address)
{
uint8_t Result;
if(Address < FRAM_SIZE)
{
output_low(FRAM_SELECT_PIN);
FRAM_xfer(FRAM_CMD_READ);
FRAM_xfer(make8(Address, 2)); //top 3 bits of address
FRAM_xfer(make8(Address, 1));
FRAM_xfer(make8(Address, 0)); //LSB
Result = FRAM_xfer(0);
output_high(FRAM_SELECT_PIN);
}
else
Result = 0;
return(Result);
}
///////////////////////////////////////////////////////////////////////////////
// write_ext_FRAM()
//
// Writes a byte to the external FRAM to the specified address. If an
// invalid address is specified nothing is written.
//
// Parameters:
// Address - the address within the external FRAM to write.
//
// Data - the byte to write to the specified address.
//
// Returns - Nothing.
///////////////////////////////////////////////////////////////////////////////
void write_ext_FRAM(FRAM_ADDRESS Address, uint8_t Data)
{
if(Address < FRAM_SIZE)
{
//Enable writes, ext_FRAM_write_enable()
ext_FRAM_write_enable(TRUE);
output_low(FRAM_SELECT_PIN);
FRAM_xfer(FRAM_CMD_WRITE);
FRAM_xfer(make8(Address,2);
FRAM_xfer(make8(Address, 1));
FRAM_xfer(make8(Address, 0));
FRAM_xfer(Data);
output_high(FRAM_SELECT_PIN);
//Disable writes
ext_FRAM_write_enable(FALSE);
}
}
///////////////////////////////////////////////////////////////////////////////
// ext_FRAM_read_id()
//
// Function for reading the external FRAM's identification.
//
// Parameters:
// Id - pointer to FRAM_ID structure to return read identification to.
//
// Returns - Nothing.
///////////////////////////////////////////////////////////////////////////////
void ext_FRAM_read_id(FRAM_ID *Id)
{
uint8_t count;
BYTE * ptr;
ptr=ID; //quicker than casting for every operation
output_low(FRAM_SELECT_PIN);
FRAM_xfer(FRAM_CMD_RDID);
for (count=0;count<sizeof(FRAM_ID);count++)
ptr[count]=FRAM_xfer[0]; //clock entire ID from chip
output_high(FRAM_SELECT_PIN);
}
///////////////////////////
///////////////////////////////////////////////////////////////////////////////
// ext_FRAM_write_enable()
//
// Function use enable or disable write functions.
//
// Parameters:
// Enable - if TRUE writes are enabled, if FALSE writes are disabled.
//
// Returns - Nothing.
///////////////////////////////////////////////////////////////////////////////
void ext_FRAM_write_enable(int1 Enable=TRUE)
{
output_low(FRAM_SELECT_PIN);
if(Enable)
FRAM_xfer(FRAM_CMD_WREN); //set the WREN bit
else
FRAM_xfer(FRAM_CMD_WRDI);
output_high(FRAM_SELECT_PIN);
}
///////////////////////////////////////////////////////////////////////////////
// read_block_FRAM()
//
// Function used to perform a block read from the chip
//
// Parameters:
// Address - start address in the memory
// buffer - pointer to RAM area to receive the data
// count - number of bytes to read
//
// Returns - Nothing.
///////////////////////////////////////////////////////////////////////////////
read_block_FRAM(FRAM_ADDRESS Address, BYTE * buffer, uint16_t count)
if(Address < FRAM_SIZE)
{
output_low(FRAM_SELECT_PIN);
FRAM_xfer(FRAM_CMD_FSTRD);
FRAM_xfer(0); //dummy byte needed after this command
while (count-->0)
*(buffer++) = FRAM_xfer(0));
//now transfer 'count' bytes ASAP
output_high(FRAM_SELECT_PIN);
}
return;
#endif
|
Last edited by Ttelmah on Mon Oct 28, 2019 8:54 am; edited 1 time in total |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sat Oct 19, 2019 6:23 pm |
|
|
Thank you very much for your work !!
I will have hardware this week, so test it and release to common library. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Oct 19, 2019 10:50 pm |
|
|
Look forward to hearing how you get on... |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sat Oct 26, 2019 3:52 pm |
|
|
Hi,
Just received assembled hardware and putting everything together.
Will keep you informed.
BR |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sun Oct 27, 2019 2:38 pm |
|
|
Hi,
Not working, until now. Need to setup a protocol analyzer to see what is done inside, as with simple dso see it properly.
More news next 1-2 days. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sun Oct 27, 2019 11:30 pm |
|
|
What PIC are you using?. What pins?. What clock rate?.
OK I've just spotted one error. Made a one line change to the posted code. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 6:37 am |
|
|
Sorry for my late replying.
Just was inside of the IC :-)
I'm using DSPIC33EP512MU810
but PCB received with bug, and now trying to solve it.
They used a wrong pin for SPI1, so the only solution was to use common PIN for SDO and SDI as software SPI is too slow for this.
BAUD=16000000
Code: | #define FRAM_HOLD_PIN PIN_A14
#define FRAM_WP_PIN PIN_A5
#define FRAM_SELECT_PIN PIN_A15
#define FRAM_CLK_PIN PIN_F1
#define FRAM_SDI_PIN PIN_G1 //MOSI
#define FRAM_SDO_PIN PIN_G1 //MISO
#define FRAM_SIZE 524288 //4Mbit 500Kbytes
#define FRAM_SPI_BAUD 16000000 //16 MHz
#pin_select REFCLK = PIN_G13
/////////////// SPI Set-up START ////////////////
#pin_select SCK1OUT = PIN_F1 //DSP Pin 66
#pin_select SDI1 = PIN_G1 //DSP Pin 68 MOSI1 DO PIN_G7
#pin_select SDO1 = PIN_G1 //DSP Pin 67 MISO1 DI PIN_G6
#use spi(MASTER, SPI1, FORCE_HW, MODE=0, BITS=8, SAMPLE_RISE, MSB_FIRST, BAUD=16000000, stream=FRAM_STREAM) |
Soon will be back to you with positive news (hope and wish).
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Oct 31, 2019 7:30 am |
|
|
That is going to give you major issues.
Problem is SDO drives the pin, so data can't be received on it from the chip.
You are going to see unwanted heating when both chips try to drive, and
going to have to change the TRIS explicitly in the code whenever data
actually wants to be read. I have a nasty suspicion it is not going to work.
Honestly better to cut the 'wrong' track and make a hardware bodge. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 7:59 am |
|
|
OK. Thank you, taking my knife for action and microscope
soon back to you |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 8:44 am |
|
|
Found that F8 is used as test point, so easy to solder a wire, as to 100 pins TQFP is very difficult to solder anything on pins, so isolated the FRAM SO, but pushing it up, and solder a bridge to F8, checking now.
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Oct 31, 2019 8:56 am |
|
|
I've learnt the 'delights' of making changes to SM chips. Found it worth
bringing anything I've not already debugged to a patch area near the chip
when laying out the PCB. Saves a lot of grief.... |
|
|
|