[samc] SERCOM interrupts - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: April 15, 2020, 06:12:01 pm
content: I created some code to send data over a sercom port in SPI mode.First I enable the interrupts then send the first byte off. The subsequent bytes are loaded in an interrupt routine which ends by re-raising the CS line.Problem, I send "hello" but I get out "ello", I figured that somehow it was like the first byte load was being ignored and the sercom was going straight into send mode. So I change my code so that the interrupts are enabled after the first byte is sent and now the whole "hello" comes through.I am confused as to how the interrupt can immediately trigger. It would appear that the circuitry that detects an empty buffer immediately fires an interrupt without even needing a byte to have been sent first!I am kind of inclined now to put activating the interrupt in the send code as I now have it and then disable the damn thing to stop it constantly triggering.Given the two layers of interrupt on an ARM I am pondering just enabling the full set of interrupts on the NVIC and then enabling them on the peripherals as and when strictly needed.

author: ataradov
author_rank: Super Contributor
timestamp: April 15, 2020, 06:49:25 pm
content: There are many interrupt flags. What specific ones do you handle?If you are using interrupts, then don't put any data first. Just enable DRE interrupt and put the first and consecutive bytes there.

author: Simon
author_rank: Unknown
timestamp: April 15, 2020, 06:53:07 pm
content: i am using the buffer empty and transmission complete interrupt. Are you saying to put all of the send data in the interrupt routine and then enable the interrupt to start transmission? I was just going to save one unnecessary interrupt call but yea makes sense I guess.

author: Simon
author_rank: Unknown
timestamp: April 15, 2020, 09:41:34 pm
content: hm, the datasheet on the baud register page for SPI links to the asynchronous baud description but I thought SPI was synchronous. I used the synchronous calculation and have the expected baud rate.... so.... is the datasheet wrong?

author: ajb
author_rank: Super Contributor
timestamp: April 15, 2020, 10:38:57 pm
content: The DRE interrupt flag is set whenever the data register is empty, which it will be if the previous transaction was completed properly. That's why it triggers immediately if you enable the interrupt before loading the first byte into the register.I don't remember if this applies to the SAMC series, but some parts have a 'transmit complete' interrupt flag, which is set at the moment of completion, but if cleared manually will stay cleared. In that case, as long as the TXC flag is cleared you could enable the TXC interrupt and then load the data register. But this is actually different behavior than the DRE interrupt, as DRE flag will often be set before the transmission is actually complete, so often what you want to do is use the DRE interrupt to trigger loading the second and subsequent bytes, and then use the TXC interrupt to release the CS line (or do whatever else you need to do when the transaction is finished). If you use the TXC for every byte of the transaction there may be a slightly longer gap between bytes than if using the DRE, since there's a de facto double-buffer between the data register and the shift register that is connected to the TX line.

author: ataradov
author_rank: Super Contributor
timestamp: April 15, 2020, 11:07:18 pm
content: Quote from: Simon on April 15, 2020, 09:41:34 pmThere does not seem to be a linkable section for the synchronous mode, so all BAUD registers just refer back to asynchronous section.It is hard to tell what may be wrong without looking at the code.On the first write to the DATA register, DRE interrupt will be set almost instantly as the written data is transferred into the shift register. Reacting to only DRE should be sufficient, since after the second write to the DATA register, DRE flag will take the duration of the byte to be set.RXC and TXC is essentially the same flag for the SPI, since receive and transmit completes at the same time.If you are sending data on the DRE flag, which is the right way to go, then you still need to wait for TXC for the last byte before releasing the CS.

author: Simon
author_rank: Unknown
timestamp: April 16, 2020, 07:46:30 am
content: Quote from: ataradov on April 15, 2020, 11:07:18 pmCorrect, my first iteration just used the register empty flag and the CS line was raised too fast before the last byte completed. So I used the transmit complete but as mentioned above that introduces a delay so I then differentiated. Of course now I have two small bodies of code in the interrupt handler, one for each. If I were not to be bothered by the slight cycle extension I could do it all on the transmit complete flag. I expect that as eventually the handler will have to check most flags it makes no odds. I don't know at what speed of transmission it no longer makes sense to bother with interrupts as it would take as long to get in and out of the interrupt as it would to send each character but I suppose the net result is the same and I am currently working with a reasonably slow speed.