Forum Rule: Always post complete source code & details to reproduce any issue!
Page 9 of 9 FirstFirst ... 7 8 9
Results 201 to 206 of 206

Thread: IFCT - Improved Flexcan Teensy Library

  1. #201
    Junior Member
    Join Date
    Feb 2017
    Posts
    18
    ah - that may explain why it did run at the first stage just until I thought enhancements would be needed for something else. Well, I changed the meaning of my own protocol bytes so that's not a problem any longer. Thanks anyway - it help to understand!

    But man, I'm still having problem to understand the TX side deeply: When I lower my sending rate, things are smooth without congestion and the receiving end catches up without any backlog. But I need higher rates and I'm sure that the bus is not saturated so it has to be software runtime issues?!

    I apologise but I have some more questions:
    - one of my application runs fine without msg.seq=1 with 6 TX mailboxes to deliver in. But as soon as I do msg.seq=0 and I send one frame, it locks itself up for almost a whole second then the 2nd frame is sent etc... same code, same receiver... So what could lead into this situation? Shouldn't depletion be decoupled from sequencing as long as there are enough TX mailboxes?

    - Where do I see or configure the TX transmit queue size? what/how is this linked to the template parameter of the FlexCan_T4 constructor?

    - does the write() complete after it get's the ACK from the receiving node or is this asynced?

    - does the receiving callback have to run through until the next call can be processed? or can they be "overrun" leading into consistency problems (overwriting volatiles) and depending on the previous question, lead into congestions on the bus?

    - Can0.events() doesn't seem to return anything? I thought that is useful to understand the queue capacity?!

    - there is no timeout argument in this library (or not yet?) - so not control for retries or timeout parameters? correct?

    Maybe it's lack of my knowhow and documentation but maybe a couple of instructions would be needed for anybody that run into "congestions/locked/hanging" problems especially when dealing with sender and receiver code. Maybe there are some best practices what to do and what not to do. In my application it's about realtime, low-latency, continuous small messages (either 8 frames with 1 byte or 1 frame with 8 bytes, with ext IDs) from a master node to a client node. Bus arbritation/layer 1 prio is only needed when there is another type of message (another message ID) on the same bus, if that happens, I'd like to have some control of priority, those are messages that come every now and then, so not at a constant rate. The reason I went for MB's is to get some convenience to sort the messages based on the type (the message ID, really). But maybe in my application all I needed was a FIFO sending as fast as possible and on the receiver do the "triage" in one FIFO callback (parse based on message ID etc... all in software)....

    Could you spend some minutes on this, please? I'm happy to pay for your time or donate something!

    Thanks.

  2. #202
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,205
    The RX and TX queue are sized from constructor, as a power of 2.

    The write is complete (but not yet transmitted) when a TX mailbox is available and your data is written to it. It is non blocking, and relies on the hardware to handle the arbitration to fully transfer it to the bus. The function returns 0 or 1, basically 0 if no mailboxes were available (so you can know if you need to resend) or 1 if a mailbox was written successfully. The rest is done in hardware, so it's up to the transmissions and controller to finalize and clear the mailbox. The library will only see free mailboxes to be written to.

    Can0.events() is mandatory only when used for Interrupt enabled receptions (FIFO or MBs), and for sequential sends. Sequential sends is only stored in the queue, and they only write to the absolute first transmit mailbox. All other transmit mailboxes are not used in sequential sends. Normal sends fill up all available TX mailboxes, and are not queued. Mailbox + FIFO polling receptions, and normal sends do not need events().

    For retries, a user can handle this with his own timer, and the return flag. If a 0 is returned, it means you need to either resend again or set your own timer to resend the frame. It's easier just to take note of the return flag, to know how to handle the resends.

    Happy to help, but this is a hobby to me and I support the forum, PJRC, and it's users, and I don't expect anything in return

    Also, you can use sequential TX alternatively. The return value of the last 12 bits show how many messages are in queue. if your TX QUEUE is:
    Code:
    FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can0;
    this means you have 16 queues. So when sending a sequential frame, we don't monitor the return of the write function, because it is different behaviour. For sequential sends, the absolute first mailbox is the only transmit mailbox used for sending. If it is empty, it will be filled and 1 returned. If it is full and you write another frame, 1 can still be returned, as it's stored in the queue. The only time 0 will appear is if the queue is being filled faster than it can unload. The queue is only processed via events() so that must always be ran to push frames in-order into transmissions.

    if ( Can0.events & 0xFFF ) { /* if there are queues to be transmitted */
    while ( Can0.events & 0xFFF ) { /* while there are queues to be transmitted */

    Or handle the resends based on the queues if theyre maxed
    if ( (Can0.events & 0xFFF) == 16 ) { /* queues full, resend if necessary */

    There is always room for adding improovements, my other library blasts the whole queue with data and polls events() until the transmissions are done. It was noted by skpang, an LCD line buffer of 640 bytes with header info on a 1MBps nominal, 8Mbps data bus resulted in 1.5ms total transfer. It's not CAN2 speeds but it is pretty fast, even for single mailbox sequential sends.


    Code:
    uint32_t timeout = millis();
    if ( (Can0.events & 0xFFF) > 10  ) while ( (Can0.events & 0xFFF) && (millis - timeout < 100) );
    This code basically tries to transmit the frames in the queue when more than 10 are consecutively queued if your loop() is not fast enough to run events(). It has it's purpose and probably there can be a function made to make it easier for the user, functionality is there though.
    Keep in mind that if you write 20 frames to transmit sequentially before you hit the events(), you'll just overflow and lose your queues. It is very important that events() is ran just as fast as you can send, this usually works better in tight loops, or with hardware timers, or teensythreads, or just managing looping events till your queues deplete. You can always choose a bigger queue, if you plan to send 100 messages per second, set a TX queue of 256, blast it, then poll events() checking the last 12 bits to push them onto the network
    Last edited by tonton81; 01-24-2020 at 01:57 AM.

  3. #203
    Junior Member
    Join Date
    Feb 2017
    Posts
    18
    OK thank you very much.
    However, Can0.events does not extist and Can0.events() doesn't return an int:

    error: invalid operands of types 'void' and 'int' to binary 'operator&'
    if ( (Can0.events() & 0xFFF) > 10 ) while ( (Can0.events() & 0xFFF) && (millis - timeout < 100) );

  4. #204
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,205
    Please make sure you update the repo, it was a month or so ago that was added

  5. #205
    Junior Member
    Join Date
    Feb 2017
    Posts
    18
    ok thanks - will do.
    One additional questions - this time on the receiving side:
    What's the effect of the RX buffer when working with callbacks? Wouldn't the callback fire as soon as one frame went through the filters (of the associated MB)? What's the point to buffer on RX side? Using callbacks the code is always "picking up".

    What happens on long running callbacks i.e. the next packet invokes the callback before the first one exists? Is that the buffer?

    I think I have a long running callback and while fast sending is OK the code seems to catch up with the fast sending rate but then at irregular times it will stop calling the callback (but the main loop continues) for about 1 second, then it continues to match the rate for another seconds - this repeats on and on.... How can I narrow this down to understand where/why the code "hangs"?

    Thanks for far - I'm almost there ;-)

  6. #206
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,205
    The receive buffer is only used when using interrupts, not when polling.
    The ISR only drops the frames in the queue, the callback fires when events() in the loop is ran and queues exist. So you process the queues in your code while the ISR just buffers it in the queues

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •