You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are two programs here, the first is the firmware for the STM32F407 and the second is a small CLI app which is intended to be executed on a RPI which is communicating with the MCU via an SPI device (/dev/spidev1.1 in my case).
Incoming messages can come in at anytime as long as the MCU is not trying to return data. This can be cross-checked by looking at the busy line (it should be low and then you are good to go to transmit a command)
Each command has a response to act as an ACK
There is no real error checking here
Commands are executed in FIFO style
Commands and responses are limited to 32 bytes of data
Protocol
The protocol is simple. This is a one-direction-at-a-time (C) approach. I thought of trying to do full duplex but it the juice was not worth the squeeze and it was really going to complicate things. (at least I think).
Packets are received by the MCU with the following structure:
Offset
Size
Description
0
2
Message ID
2
2
Opcode
4
N
Message Data
The MCU knows when the packet is completed because it gets the close of the SS line on the SPI.
Each message gets a response. In this way, one can get some information that the MCU did get the message. The structure of the response is the following:
Offset
Size
Description
0
2
Message ID
2
2
Size in Bytes of follow-on data in this message
4
N
Any data returned from the request
Concept of Operation
The firmware starts off by establishing two BBQueue's, one for incoming commands and one for outgoing responses. The SPI device and the DMA are configured and the spi_complete task is pended. The spi_complete task does two things, first it commits any existing write grant on the incoming command queue. It then establishes a new grant and configures the DMA with that memory address. By initially pending the spi_complete task, I keep all of the write grant code for the incoming command queue in a single function and reduce code duplication. A
After a command is delivered to the MCU, the spi_complete task executes because of the interrupt and commits the new command to the processing queue. The process_command task is then spawned which attempts to loop over all existing commands in the incoming command queue. It essentially performs the correct task, formats the return, writes the return to the outgoing response queue, and finally spawns the transmit_command_results task.
The transmit_command_results task changes the state of the SPI device to "SendingResponse", gets a read grant from the outgoing queue, and sets up the DMA to use it. Lastly, the task tells the master that there is data ready for pickup by raising a GPIO pin that the master can watch. This triggers the master to perform an spa read. The master does a mandatory 4-byte read on the bus and then decodes the follow-on message data size and the message id from the 4 bytes. If there is any more data it needs to pull, it will then do a follow-on spi read with the appropriate size.
The firmware knows all of the data has been read by the NCTR register of the TxDMA going to 0 and the DMA completed event is fired. This resets things and gets ready for the next round.
Potential Change to Firmware
A thought I had was to just get rid of the incoming command queue and have a simple buffer to receive commands. As each command was received, it would fire off the process_command task while directly passing it the raw command data. As soon as the command was processed, the result would go into the command response queue and the firmware would continue to operate as it currently does.
The benefit of this is a simpler application and the ability to complete tasks without blocking. For instance, if there were two commands which were executed, one long run-time and one short run-time. If the long one is sent first then the short one would have to wait for completion of the long runtime command. With this change, maybe the short runtime gets done quickly, while the long runtime task is running, and the result is made avail to the master in an out-of-sync fashion (command 2 response before command 1 response)?
Not sure, just food for thought.
The CLI Application
The CLI is most likely very very buggy and was just a copy to play with and give me an interface to generate requests. This is holding the place of a server which would be running on the RPI (prob a Rocket server?). The app just presents a simple screen with a table. When you hit the 's' command it would send a pre-formatted SPI command to the MCU and then grab the response when it is ready. Rows in red color do not have a response yet, rows in green have received a response from the MCU.
Targeted Questions
Should I switch to the mode that I was talking about where I drop the rx queue?
Should I be using other great things that you have put together such as Postcard?
Am I crazy?
The text was updated successfully, but these errors were encountered:
There are two programs here, the first is the firmware for the STM32F407 and the second is a small CLI app which is intended to be executed on a RPI which is communicating with the MCU via an SPI device (/dev/spidev1.1 in my case).
Firmware: https://github.com/justacec/stm32f407_play
CLI App: https://github.com/justacec/test_spi_cli
Core Concepts
Protocol
The protocol is simple. This is a one-direction-at-a-time (C) approach. I thought of trying to do full duplex but it the juice was not worth the squeeze and it was really going to complicate things. (at least I think).
Packets are received by the MCU with the following structure:
The MCU knows when the packet is completed because it gets the close of the SS line on the SPI.
Each message gets a response. In this way, one can get some information that the MCU did get the message. The structure of the response is the following:
Concept of Operation
The firmware starts off by establishing two BBQueue's, one for incoming commands and one for outgoing responses. The SPI device and the DMA are configured and the
spi_complete
task is pended. Thespi_complete
task does two things, first it commits any existing write grant on the incoming command queue. It then establishes a new grant and configures the DMA with that memory address. By initially pending thespi_complete
task, I keep all of the write grant code for the incoming command queue in a single function and reduce code duplication. AAfter a command is delivered to the MCU, the
spi_complete
task executes because of the interrupt and commits the new command to the processing queue. Theprocess_command
task is then spawned which attempts to loop over all existing commands in the incoming command queue. It essentially performs the correct task, formats the return, writes the return to the outgoing response queue, and finally spawns thetransmit_command_results
task.The
transmit_command_results
task changes the state of the SPI device to "SendingResponse", gets a read grant from the outgoing queue, and sets up the DMA to use it. Lastly, the task tells the master that there is data ready for pickup by raising a GPIO pin that the master can watch. This triggers the master to perform an spa read. The master does a mandatory 4-byte read on the bus and then decodes the follow-on message data size and the message id from the 4 bytes. If there is any more data it needs to pull, it will then do a follow-on spi read with the appropriate size.The firmware knows all of the data has been read by the NCTR register of the TxDMA going to 0 and the DMA completed event is fired. This resets things and gets ready for the next round.
Potential Change to Firmware
A thought I had was to just get rid of the incoming command queue and have a simple buffer to receive commands. As each command was received, it would fire off the
process_command
task while directly passing it the raw command data. As soon as the command was processed, the result would go into the command response queue and the firmware would continue to operate as it currently does.The benefit of this is a simpler application and the ability to complete tasks without blocking. For instance, if there were two commands which were executed, one long run-time and one short run-time. If the long one is sent first then the short one would have to wait for completion of the long runtime command. With this change, maybe the short runtime gets done quickly, while the long runtime task is running, and the result is made avail to the master in an out-of-sync fashion (command 2 response before command 1 response)?
Not sure, just food for thought.
The CLI Application
The CLI is most likely very very buggy and was just a copy to play with and give me an interface to generate requests. This is holding the place of a server which would be running on the RPI (prob a Rocket server?). The app just presents a simple screen with a table. When you hit the 's' command it would send a pre-formatted SPI command to the MCU and then grab the response when it is ready. Rows in red color do not have a response yet, rows in green have received a response from the MCU.
Targeted Questions
The text was updated successfully, but these errors were encountered: