Project: SPI_MSTransfer

i might work on a new feature of circular buffer for different usage capability
if you need a queue updated before it gets pulled ill have an updater function iterate over the arrays to find a match, then replace it with current updated array

this could be a major feature that others might use! (ex serial output to uart displays as example)
 
My kitchen sink is good, though needs a new faucet - I do need like 3 bathroom sinks - can you put those in before the kitchen sink?

Could the user get data pointers and methods to do things like that manually? That is: is enough stuff public to allow a user to do this kind of stuff in their own code?

Someone will always want something a bit different ...
 
yeah but if i do the iterator and update built in, its less work for user and code, secondly, it can do it “behind the scenes” on the queues not accessible to user (between head and tail)
currently its not possible to do this

even i might have a use for this making another library for other project
 
So that is a no on the bathroom sinks then?

By all means if it is simple and could be useful and not fatten the code GitRDun. Just wondering if it could be done with user code - or if a simple change to support it would allow that or similar features without editing the core code. I'd have to read it again to see the use case for what you want to add - so it seems about as odd as bathroom sinks when everyone always wants the kitchen sink thrown in :)
 
user has access to head and tail (fifo/lifo) not in between

my proposal is if a user was writing commands to a device and the same command had a comparator of the first 3 bytes (3 being specified by user) and it still existed in queue before being pushed to the device (lcd), the entry would be updated rather than appended to a new entry thereby preventing duplicates while keeping queue entries up to date
 
of course if u dont use that feature it wont affect current system, it will be a new method for its usage, that goes from head to tail entries in a circular fashion to update the queue entry if a match was found
 
just got home and its still 0 errors tim, pushing 49uS with debughack data callbacks both ways 10ms both sides sending each other
 
yeah, i moved back to yours now, just cuz i like to see both sides hammering each other at 0ms rates :)

EDIT 10:52am, theyre still going crazy at each other, the mcu cores are not hot either, running quite stable
 
Last edited:
Updating to github SPI_MSTranfer code

T_3.1 Slave to T_3.6 running since 3/11- about 9 days. :: F&F (OT=4)micros() _time==56

The first three were there with 'reset' of the Slave.
 
Master T_3.6 and Slave T_3.1 compiled and running fine.

Still 10 LED pinToggle per second at 500 Hz :: if ( millis() - _timer >= 2 )


Split the DEBUGHACK to F&F_PacketID==60.
> Works

Modified Master to send #60 and then about every 25 sent a standard #55 so lots of short DEBUGHACK prints with an occasional Full Print from the Slave. Had to put in a JUMP +12 after a #55 precedes a #60, or it reported failed missed 12.

Then modified Slave to "NVIC_SET_PRIORITY(IRQ_SPI0, 99)" - I saw one batch of failures go by and correct. And another two or so have happened as well:
M >> F&F (OT=15)micros() _time==51
S >> 25388.000000, 0.0254, 0.0254,1454797.000000,1454854.375000,25393.0000, 159.3549, 159.3581, 159.3612,25397.0000,25398.0000,25399.0000
S >> 25400.00, #, #, #, #, #, #, #, #, #, #, #,361916,17

After 165,000 F&F's I set the NVIC_PRI to 19 and restarted, no errors after the one reported by SLAVE on startup.

Added specific counter to do a #55 after each 25 #60's - Master show's 0 OT's and Slave reports 15 failures after 890,000 F&F's [ plus 1/25th more for the #55's I sneak in ]

<EDIT>: Finally captured the error info - it is overlap on wrap around on the 65536 tracked value with intermixed #55's- ... added fix for that and also the startup case where #55 precedes #60
 
Last edited:
i saw a thread somewhere where paul mentioned theres no set priorities lower than 32, 0-31 should be okay, but because the master deserves priority access i think we should keep it highest priority(<32) so it can manage the slave over SPI
 
NO LONGER SEEING ANY ERRORS - they were all caused by altered Master output test path replacing DEBUGHACK that needed catching in Slave.

tonton81 - made a Pull Request to get updated versions with new names for TVMaster and TVSlave.

Left the lowered priority at #19 :: NVIC_SET_PRIORITY(IRQ_SPI0, 19); // set priority

Compiled and tested with current CircularBuffer version of SPI_MSTransfer for my T_3.6 Master and T_3.1 Slave combo. It cleaned up the primary TVslave TViewer #55 F&F used for the IMU_GPS code, remove unused configs.h file.

Added a TVslave #56 placeholder if anyone wants to format a new TViewer string

Modified TVMaster and TVSlave to push/accept #60 F&F's that are printed in the slave as DEBUGHACK was - Terse output

TVMaster as provided will push out a #55 normal FULL LENGTH TViewer string after each 25 #60's - proves output can work and quick USB stress for longer string
 
i saw a thread somewhere where paul mentioned theres no set priorities lower than 32, 0-31 should be okay, but because the master deserves priority access i think we should keep it highest priority(<32) so it can manage the slave over SPI

For some reason I recall Paul noting that the 256 PRI levels are banded in groups of 8, i.e. 0-7 (etc) are treated the same? I picked 19 as in any case that allows at least two levels of higher priority. For some reason I saw error cascades as noted at pri==99.

So far after last re-compile before pull request is over 730K F&F's with ZERO errors noted on either end.
 
its a shame how c++ stl containers can cause so much damage when dealing with ISRs, no reason to use them anymore at this point with cb-ca, although my other library uses it, it doesn’t use it in an ISR so I can leave it like that

we could also create a circular debug buffer, and have a central switch, where it would print from the loop instead of the ISR, maybe 32 or 64 uint8_t circular queue (non array version)

that way we dont need ( if debugSerial != nullptr ) in all the debug locations, we can print directly to the buffer and only have 1 condition check during loop
 
its a shame how c++ stl containers can cause so much damage when dealing with ISRs, no reason to use them anymore at this point with cb-ca, although my other library uses it, it doesn’t use it in an ISR so I can leave it like that

we could also create a circular debug buffer, and have a central switch, where it would print from the loop instead of the ISR, maybe 32 or 64 uint8_t circular queue (non array version)

that way we dont need ( if debugSerial != nullptr ) in all the debug locations, we can print directly to the buffer and only have 1 condition check during loop

I mentioned debug buffer before. My use case was log EVERY character of SPI transaction with time since prior character (whatever might be meaningful to understand where the errors creep in) - if it succeeds - delete the entry. Time could be with CycleCounter - millis too low res and micros() too much overhead. Not sure what else could matter or point to any common point of messages failing?

But yes, that could then be handled AFTER the fiasco clears outside the isr - or even the Master retry - those master retry messages are way too long - they could be very very short during retry - and then when succeeded the verbose data could be shown could.

<edit> OF COURSE my demo is about 1.6 M F&F's and no error so it would be a good test of cb utility and speed - and when an error shows up - we might no why?

Could keep the last 5-10 errors and then print on request of the SerMon
 
Having a static ca of logged errors could allow dumping it on command from the Serial SerMon Terminal.

My combo 30 MHz SPI on the TV examples with T_3.6/T_3.1 shows No Errors:
Master== (OT=0)
Slave notes 15,846,807 #60 debug F&F which also implies 633,872 Full #55 prints and 316,936 pinToggles:
37016.00, #, #, #, #, #, #, #, #, #, #, #,15846806,0
37028.000000, 0.0370, 0.0370,2121720.000000,2121777.250000,37033.0000, 192.4422, 192.4448, 192.4474,37037.0000,37038.0000,37039.0000
37040.00, #, #, #, #, #, #, #, #, #, #, #,15846807,0
 
Code:
  Circular_Buffer<uint8_t, 64> c5;
  Serial.println("----------------------");
  c5.print("Hello SPI_MSTransfer, ");
  c5.print("from ");
  c5.println("tonton81");
  while ( c5.size() > 0 ) {
    Serial.print((char)c5.read());
  }
  Serial.println("Proof the newline was carried into queue");

console:
Code:
----------------------
Hello SPI_MSTransfer, from tonton81
Proof the newline was carried into queue

:)

Lets do the reverse read:

Code:
  Circular_Buffer<uint8_t, 64> c5;
  Serial.println("----------------------");
  c5.print("Hello SPI_MSTransfer, ");
  c5.print("from ");
  c5.println("tonton81");
  while ( c5.size() > 0 ) {
    Serial.print((char)c5.[COLOR="#FF0000"]pop_back()[/COLOR]);
  }
  Serial.println("Proof the newline was carried into queue");

Output:

Code:
----------------------

18notnot morf ,refsnarTSM_IPS olleHProof the newline was carried into queue

oh dear lord, how silly of me, why dont i buffer those prints?

Code:
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::print(const char *p) {
  if ( multi ) return;
[COLOR="#FF0000"]  for ( uint16_t i = 0; i < strlen(p); i++ ) write(p[i]);[/COLOR]
}

template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::println(const char *p) {
  if ( multi ) return;
[COLOR="#FF0000"]  for ( uint16_t i = 0; i < strlen(p); i++ ) write(p[i]);
  write('\n');[/COLOR]
}

becomes:

Code:
template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::print(const char *p) {
  if ( multi ) return;
[COLOR="#FF0000"]  write((T*)p,strlen(p));[/COLOR]
}

template<typename T, uint16_t _size, uint16_t multi>
void Circular_Buffer<T,_size,multi>::println(const char *p) {
  if ( multi ) return;
 [COLOR="#FF0000"] write((T*)p,strlen(p));
  write('\n');[/COLOR]
}
 
Last edited:
Hi All,

I've been reading throughout development of this library and decided it's time to try it myself. Unfortunately, I'm having trouble getting the master and slave to communicate.


I used the wiring as described here, running the TVmaster and TVslave examples with no modifications from the "eaeb407" commit (latest at the time of posting). Master is the 3.6 and the slave is the 3.2. Both are confirmed to work well, and the connections tested for continuity.


Here is an image of my setup: https://imgur.com/a/gFZhF#QK0aQln
 
wheres the ground signal between both? :) the high speed SPI needs a link between, not common

the chipselect wire is missing. the slave chipselect pin is PIN 2. tie it to a master gpio, and use the pin in the master’s constructor in the sketch

just rechecked, your ground link is fine, but you need chipselect (CS) wire, can be any master pin, but must be pin2 of slave
 
Back
Top