I'm wondering what the best way to handle SPI transactions when using interrupts is.
I'm about to write my SPI interface code to an external flash part using a PIC. I'm going to use interrupts and I know that I'll get one after my byte is transferred, and after one is received. A typical 16 bit write transaction will look like this:
REGISTER_ADDRESS_BYTE | REGISTER_ADDRESS_BYTE | DATA_BYTE | DATA_BYTE | MAYBE_MORE_DATA_BYTES
Typically what I do is have a function like this pseudo code:
SendBytes(num_bytes, *ptr_to_bytes, address, init_true, callback_function_address);
Then in my SendBytes(...)
I have a state machine with two static variables, one keeps track of the state, the other keeps track of the number of bytes sent. As interrupts come in I call SendBytes(...)
again with init_false
and step through my state machine for each byte of the transaction. When I'm all done I either stop or call the stored call_back_function
.
My question is this a decent way to handle this, is there a better way using interrupts? I just made this up thinking about the problem but I assume others have had to handle this as well.
-
\$\begingroup\$ Let me back up and ask you: why do you want to use interrupt for doing the SPI master? Polling for flags (without interrupt) is another option. Polling tends to be simpler, arguably. \$\endgroup\$Nick Alexeev– Nick Alexeev2015年01月10日 19:54:12 +00:00Commented Jan 10, 2015 at 19:54
-
\$\begingroup\$ I agree that polling is easier but I want to do other real time things while my spi command is running across my relatively slow spi bus. \$\endgroup\$confused– confused2015年01月10日 20:47:12 +00:00Commented Jan 10, 2015 at 20:47
-
4\$\begingroup\$ It seems odd to use the same function to initiate transfers and to handle the interrupts. Wouldn't it be cleaner to have separate functions? \$\endgroup\$Dave Tweed– Dave Tweed2015年01月10日 21:33:59 +00:00Commented Jan 10, 2015 at 21:33
-
\$\begingroup\$ Sure I could use two functions, I'm more curious about the state machine and static variable for state approach though. \$\endgroup\$confused– confused2015年01月11日 05:36:40 +00:00Commented Jan 11, 2015 at 5:36
1 Answer 1
You didn't mention the PIC variant; SPI peripherals as well as interrupt controllers are different in different PICs. Here is an example of handling similar problem using PIC16:
https://github.com/felis/DMCI-XC8/blob/master/bsp.c#L91
It also shows state machine approach.
-
3\$\begingroup\$ Can you sumarrize that a bit? Link - only answers die when the link dies. \$\endgroup\$Scott Seidman– Scott Seidman2015年01月12日 01:29:11 +00:00Commented Jan 12, 2015 at 1:29
-
\$\begingroup\$ summarize what? And what is wrong with a link? \$\endgroup\$Oleg Mazurov– Oleg Mazurov2015年01月12日 01:54:03 +00:00Commented Jan 12, 2015 at 1:54
-
2\$\begingroup\$ Summarize your approach. What's wrong with links is that they can die, so a link should not be a the only piece of information in the answer. More about link-only answers in this post on meta.SE . \$\endgroup\$Nick Alexeev– Nick Alexeev2015年01月12日 01:59:59 +00:00Commented Jan 12, 2015 at 1:59
-
\$\begingroup\$ I have a queue which is consumed by an interrupt. When I put [the first] byte into [an empty] queue I set the interrupt [enable] flag. Actions in square brackets are architecture dependent, on some PICs it's better to disable the interrupt for the given peripheral (can't be done on PIC16). \$\endgroup\$Oleg Mazurov– Oleg Mazurov2015年01月12日 02:24:09 +00:00Commented Jan 12, 2015 at 2:24