View previous topic :: View next topic |
Author |
Message |
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 9:25 am |
|
|
Hardware corrected, now back on DSO and checking.
It is a real time debugging ;-) |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 11:04 am |
|
|
Working properly, cleaning up the source and release by tomorrow
BR |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 1:10 pm |
|
|
Reading speed for 1 byte is 450 ns, same with writing of one byte. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Oct 31, 2019 1:46 pm |
|
|
I'd have expected the write to be a bit slower than the read.
The block read should be much faster per byte. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Thu Oct 31, 2019 2:56 pm |
|
|
It is an external memory for A/D data collection from 3 x 32 bits + time stamp.
Not super fast but OK. So, Block can also be used, but not expect to have it very much faster. I will test it and report. I have 2 FRAMs on this PCB, for such buffers - 1GB totally (expensive experience)
I must thank again you for your help, it was very significant input that forced me to make this part rapidly.
I tried the SPI with various speeds (16M, 32M as also 40M) always the same W/R speed, so the bottle neck is on the routine itself than in the FRAM.
Tomorrow I will clean up the routines, make them more generic and then release to library forum. Maybe I delay it for one more day as I will test more configurations and see if I can speed it up little bit.
Thank you again.
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Nov 01, 2019 12:36 am |
|
|
I hope I got close. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Fri Nov 01, 2019 6:25 pm |
|
|
Hi,
I'm trying to implement also to this external SPI memory a circular buffer,
seems that the well known implementation used in the EX_SISR code is not easy to implement. My data package is 22 bytes long. I need to store each time a record, and read time to time (like a fifo-circular buffer).
Have anyone an idea about how to implement circular buffer in SPI external memory ?
Thank you in advance.
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Nov 01, 2019 11:59 pm |
|
|
The basic circular buffer code can be used
All you need to do is declare your package as a struct. Then read and
write these structures as the entities stored. You will then simply have
to multiply the indexes used by the sizeof the structure to get the address
in the FRAM. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sat Nov 02, 2019 3:14 am |
|
|
I have had exactly the same idea and already testing this.
So, you confirmed that I'm in a good way.
Thank you and Kind Regards. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Nov 02, 2019 4:20 am |
|
|
Years ago, I wrote a set of macros for this type of thing. Dug back:
Code: |
typedef struct
{
int32 start_addr;
int32 in;
int32 out;
} buffer_def;
#define BUFFER_COUNT 0x4000 //my buffer supported 4000 entries
buffer_def data_ptr={0x1000, 0, 0}; //my buffer was in EEPROM starting
//at 1000
struct
{
int32 time;
float value;
int16 status;
} data; //The temporary record used.
int32 temp_addr;
int temp_ctr;
#define JOIN(x,y) x##y
//Macro to allow buffer register values to be built
//Macros all called with buffer name as first value
#define CLEAR_BUFFER(x) JOIN(x,.in)=join(x,.out)=0;
#define INC_IN(x) if(++JOIN(x,.in)>=BUFFER_COUNT) join(x,.in)=0
#define INC_OUT(x) if(++JOIN(x,.out)>=BUFFER_COUNT) join(x,.out)=0
#define IS_EMPTY(x) (JOIN(x,.in)==JOIN(x,.out))
//Here needs pointer to data record, and size as next two values
#define GET_NEXT(x,d,s) temp_addr=(JOIN(x,.out)*s); \
for (temp_ctr=0;temp_ctr<s;temp_ctr++) \
*((byte *)d+ctr)=read_ext_eeprom(temp_addr++); \
INC_OUT(x)
//as above
#define ADD_ENTRY(x, d, s) temp_addr=(JOIN(x,.in)*s); \
for (temp_ctr=0;temp_ctr<s;temp_ctr++) \
write_ext_eeprom(temp_addr++, *((byte *)d+ctr)); \
INC_IN(x)
|
I stored the data_ptr record, into NVRAM (in a clock chip), so it didn't
matter updating it every time a record was added or retrieved.
Used as:
Fill up the 'data' variable. Then
ADD_ENTRY(data_ptr, &data, sizeof(data));
and
GET_NEXT(data_ptr, &data, sizeof(data));
to read the next record.
The macros then handle the buffers for you. I made them flexible since
I was actually storing three different record structures.
You can test if there is data in the buffer with 'IS_EMPTY(data_ptr)'
this returns true if the buffer is empty. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sun Nov 03, 2019 11:04 am |
|
|
micro_debugger wrote: | Reading speed for 1 byte is 450 ns, same with writing of one byte. |
I made a mistake in measurements, 450 ns is for one bit, not for one byte
The maximum speed for one byte write (with SPI running at 15MHz - this is the max speed for dsPIC) is about 10us per byte writing to FRAM.
The max speed of SPI is the reason as we can not increase the speed of it. Also between each SPI write or read, about 900ns is loosed. I tried to make various tricks in order to increase the speed little bit (as in each write/read we loose about 5 us between all SPI calls (spi_xfer) but finally not working properly, with these improvements we I step down to about 8 us per write, and 7 us per byte read, but not working properly. The dsPIC is running with bout 67 MIPS (not 70 MIPS, as a special clocking is needed for my application)
Reading of a single byte is about 9us. However it is possible to read block, and then we have much higher speeds, 100 bytes is 172 us, 21 bytes is about 40 us
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Nov 03, 2019 11:29 am |
|
|
Er. You should be able to clock the SPI up to certainly 16.75MHz, possibly even
twice this. At 16.75MHz a byte should only take 0.5uSec to transfer. You will
find the spi_read and spi_write instructions are faster than spi_xfer.
Unfortunately, the spi_xfer includes the overhead for support for multi byte
transfers even if it is not used, and this costs significantly on the performance.
At your quoted processor speed I'd have expected it to take under 3uSec
to do the entire transfer. Your 450nSec, suggests you are only clocking the
SPI at just over 2MHz. Why?. |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sun Nov 03, 2019 11:31 am |
|
|
checking again, and back soon to you.
I definitely prefer to have much faster FRAM due to my application, maybe I'm not doing something properly
Thank you for your kind answer
BR |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sun Nov 03, 2019 11:37 am |
|
|
This is the setup of my clocking, and FRAM SPI
Code: |
#include <33EP512MU810.h>
#build(stack=4096)
#use delay(clock=131072kHz, oscillator=30.72MHz, pll_wait, USB_FULL, AUX:clock=48MHz, crystal=16Mhz)
#define FRAM_HOLD_PIN PIN_A14
#define FRAM_WP_PIN PIN_A5
#define FRAM_SELECT_0 PIN_A15
#define FRAM_SELECT_1 PIN_A4
#define FRAM_CLK_PIN PIN_F1
#define FRAM_SDI_PIN PIN_D8 //MOSI PIN_G1
#define FRAM_SDO_PIN PIN_G1 //MISO PIN_F8
#define FRAM_SIZE 524288 //4Mbit 500Kbytes
#define FRAM_SPI_BAUD 15000000 //15 MHz
#pin_select SCK1OUT = FRAM_CLK_PIN
#pin_select SDI1 = FRAM_SDI_PIN
#pin_select SDO1 = FRAM_SDO_PIN
#use spi(MASTER, SPI1, FORCE_HW, MODE=0, BITS=8, MSB_FIRST, BAUD=FRAM_SPI_BAUD, stream=FRAM_STREAM)
|
The used dsPIC can not have faster SPI than 15Mhz |
|
|
micro_debugger
Joined: 08 Oct 2009 Posts: 73
|
|
Posted: Sun Nov 03, 2019 11:48 am |
|
|
Yes, you are right, it is 2MHz, not 16.
Setting up again the DSO to measure again. |
|
|
|