-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use mailbox for thread-safe data transfer, Improve SPI reliability #107
Closed
thomasfla
wants to merge
13
commits into
open-dynamic-robot-initiative:master
from
thomasfla:usemailbox
Closed
Changes from 2 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
f513965
[SDK][Firmware] Add partial support for power-board, Update protocol …
thomasfla e49b0b9
Merge branch 'master' of https://github.com/thomasfla/master-board
thomasfla 5cc30d1
add pyton bindings for power baord
2e8904e
update doc including powerboard data in sensor packets
thomasfla 8f7fd01
Merge branch 'open-dynamic-robot-initiative:master' into master
thomasfla e09fadc
Merge pull request #2 from paLeziart/bindings_powerboard
thomasfla d1d9e50
update BOM, correct C2 and R17 MPN; remove deprecated seeed BOM
thomasfla 4a5f421
Fix 0402 footprint to comply with seeed, fix HR911105A footprint, add…
thomasfla da743d9
Update production files, add xy files inside the zip
thomasfla 768f83f
Replace non thread safe ring buffer by a FreeRTOS mailbox queue
thomasfla 4706076
change CS from hardware control to software control. This adds a smal…
thomasfla 4e3c911
Rewrite IMU driver using mailbox, fixing esp32 hardware bug on uart fifo
thomasfla 013589b
Merge branch 'master' into usemailbox
nim65s File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ | |
#include "quad_crc.h" | ||
#include "uart_imu.h" | ||
#include "ws2812_led_control.h" | ||
|
||
#include "defines.h" | ||
|
||
#define ENABLE_DEBUG_PRINTF false | ||
|
@@ -56,19 +55,18 @@ struct led_state ws_led; | |
|
||
static uint16_t spi_index_trans = 0; | ||
|
||
static uint16_t spi_rx_packet[CONFIG_N_SLAVES][SPI_TOTAL_LEN + 1]; // +1 prevents any overflow | ||
|
||
static uint16_t spi_tx_packet_a[CONFIG_N_SLAVES][SPI_TOTAL_LEN]; | ||
static uint16_t spi_tx_packet_b[CONFIG_N_SLAVES][SPI_TOTAL_LEN]; | ||
static uint16_t spi_tx_packet_stop[CONFIG_N_SLAVES][SPI_TOTAL_LEN]; | ||
static uint16_t spi_rx_packet[CONFIG_N_SLAVES][SPI_TOTAL_LEN + 1]; // +1 prevents any overflow //TODO understand why we need this? | ||
static uint16_t spi_tx_packet[CONFIG_N_SLAVES][SPI_TOTAL_LEN]; | ||
|
||
uint16_t command_index_prev = 0; | ||
|
||
struct wifi_eth_packet_sensor wifi_eth_tx_data; | ||
|
||
struct wifi_eth_packet_ack wifi_eth_tx_ack; | ||
|
||
bool spi_use_a = true; | ||
struct wifi_eth_packet_command wifi_eth_rx_cmd_reader_buffer; | ||
QueueHandle_t wifi_eth_rx_cmd_mailbox; | ||
|
||
bool send_zero_cmd = true; //If true, all cmd packet sent to udrivers ar set to 0. | ||
|
||
void print_spi_connected() | ||
{ | ||
|
@@ -157,12 +155,7 @@ static void periodic_timer_callback(void *arg) | |
/* Prepare spi transactions */ | ||
bool spi_done[CONFIG_N_SLAVES] = {0}; // used to keep track of which spi transactions are done | ||
spi_index_trans++; | ||
|
||
/* Choose spi packets to send*/ | ||
uint16_t(*p_tx)[SPI_TOTAL_LEN]; | ||
|
||
p_tx = spi_tx_packet_stop; // default command is stop | ||
|
||
send_zero_cmd = true; | ||
spi_count++; | ||
|
||
switch (current_state) | ||
|
@@ -211,7 +204,12 @@ static void periodic_timer_callback(void *arg) | |
} | ||
else | ||
{ | ||
p_tx = spi_use_a ? spi_tx_packet_a : spi_tx_packet_b; | ||
send_zero_cmd = false; | ||
// Read command message in a RTOS mailbox for thread safe comunication */ | ||
if (!xQueuePeek(wifi_eth_rx_cmd_mailbox, &wifi_eth_rx_cmd_reader_buffer, 0)) | ||
{ | ||
send_zero_cmd = true; //mailbox is empty -> we never got a command packet | ||
} | ||
} | ||
|
||
wifi_eth_count++; | ||
|
@@ -253,22 +251,52 @@ static void periodic_timer_callback(void *arg) | |
} | ||
//print_imu(); | ||
printf("\nlast CMD packet:\n"); | ||
print_packet(p_tx[2], SPI_TOTAL_LEN * 2); | ||
print_packet(spi_tx_packet[2], SPI_TOTAL_LEN * 2); | ||
} | ||
|
||
/* Complete and send each packet */ | ||
|
||
// Fills the outgoing spi packet | ||
/* Prepare the outgoing spi TX packet */ | ||
for (int i = 0; i < CONFIG_N_SLAVES; i++) | ||
{ | ||
//printf("%d\n",send_zero_cmd); | ||
if (!TEST_BIT(spi_connected, i) && !spi_autodetect) | ||
continue; // ignoring this slave if it is not connected | ||
|
||
SPI_REG_u16(p_tx[i], SPI_TOTAL_INDEX) = SPI_SWAP_DATA_TX(spi_index_trans, 16); | ||
SPI_REG_u32(p_tx[i], SPI_TOTAL_CRC) = SPI_SWAP_DATA_TX(packet_compute_CRC(p_tx[i]), 32); | ||
if (!send_zero_cmd) | ||
{ | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_MODE) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].mode, 16); | ||
SPI_REG_32(spi_tx_packet[i], SPI_COMMAND_POS_1) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].position[0], 32); | ||
SPI_REG_32(spi_tx_packet[i], SPI_COMMAND_POS_2) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].position[1], 32); | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_VEL_1) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].velocity[0], 16); | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_VEL_2) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].velocity[1], 16); | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_IQ_1) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].current[0], 16); | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_IQ_2) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].current[1], 16); | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KP_1) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].kp[0], 16); | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KP_2) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].kp[1], 16); | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KD_1) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].kd[0], 16); | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KD_2) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].kd[1], 16); | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_ISAT_12) = SPI_SWAP_DATA_TX(wifi_eth_rx_cmd_reader_buffer.command[i].isat, 16); | ||
} | ||
else | ||
{ | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_MODE) = SPI_SWAP_DATA_TX(1<<15, 16); //In case of zero commands, keep the system enabled | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a constant with a speaking name for the |
||
SPI_REG_32(spi_tx_packet[i], SPI_COMMAND_POS_1) = 0; | ||
SPI_REG_32(spi_tx_packet[i], SPI_COMMAND_POS_2) = 0; | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_VEL_1) = 0; | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_VEL_2) = 0; | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_IQ_1) = 0; | ||
SPI_REG_16(spi_tx_packet[i], SPI_COMMAND_IQ_2) = 0; | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KP_1) = 0; | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KP_2) = 0; | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KD_1) = 0; | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_KD_2) = 0; | ||
SPI_REG_u16(spi_tx_packet[i], SPI_COMMAND_ISAT_12) = 0; | ||
} | ||
SPI_REG_u16(spi_tx_packet[i], SPI_TOTAL_INDEX) = SPI_SWAP_DATA_TX(spi_index_trans, 16); | ||
SPI_REG_u32(spi_tx_packet[i], SPI_TOTAL_CRC) = SPI_SWAP_DATA_TX(packet_compute_CRC(spi_tx_packet[i]), 32); | ||
} | ||
|
||
/* Send every trans the needed number of times */ | ||
/* Perform every transaction the needed number of times */ | ||
for (int spi_try = 0; spi_try < spi_n_attempt; spi_try++) | ||
{ | ||
for (int i = 0; i < CONFIG_N_SLAVES; i++) | ||
|
@@ -278,9 +306,8 @@ static void periodic_timer_callback(void *arg) | |
|
||
if (spi_done[i]) | ||
continue; // ignoring this slave if the transaction has already been done | ||
|
||
spi_send(i, (uint8_t *)p_tx[i], (uint8_t *)spi_rx_packet[i], SPI_TOTAL_LEN * 2); | ||
|
||
|
||
spi_send(i, (uint8_t *)spi_tx_packet[i], (uint8_t *)spi_rx_packet[i], SPI_TOTAL_LEN * 2); | ||
//if (ms_cpt % 500 == 0) printf("%d %d\n", spi_try, i); | ||
|
||
// checking if data is correct | ||
|
@@ -314,13 +341,14 @@ static void periodic_timer_callback(void *arg) | |
|
||
else | ||
{ | ||
//printf("%d\n",ms_cpt); | ||
// zeroing sensor data in packet, except the status field | ||
memset(&(wifi_eth_tx_data.sensor[i]), 0, sizeof(struct sensor_data)); | ||
wifi_eth_tx_data.sensor[i].status = 0xf; // specifying that the transaction failed in the sensor packet | ||
} | ||
} | ||
|
||
//Slave 7 is always the power board | ||
|
||
uint8_t tx_spi_powerboard[12]={0xaa,0xbb,0xcc,0xdd,0xee,0xff,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; //Fake packet, cmd to the power board are not yet implemented | ||
uint8_t rx_spi_powerboard[12]={0}; | ||
spi_send(7, tx_spi_powerboard,rx_spi_powerboard, 12); | ||
|
@@ -334,7 +362,6 @@ static void periodic_timer_callback(void *arg) | |
fb.b[1] = rx_spi_powerboard[8]; | ||
fb.b[0] = rx_spi_powerboard[9]; | ||
wifi_eth_tx_data.powerboard.energy = fb.f; | ||
|
||
} | ||
} | ||
|
||
|
@@ -379,7 +406,7 @@ static void periodic_timer_callback(void *arg) | |
case SPI_AUTODETECT: | ||
case ACTIVE_CONTROL: | ||
case WIFI_ETH_ERROR: | ||
/* Send all spi_sensor packets to PC */ | ||
/* Send sensors packet to PC */ | ||
wifi_eth_tx_data.sensor_index++; | ||
if (use_wifi) | ||
{ | ||
|
@@ -404,12 +431,6 @@ static void periodic_timer_callback(void *arg) | |
void setup_spi() | ||
{ | ||
spi_init(); | ||
|
||
for (int i = 0; i < CONFIG_N_SLAVES; i++) | ||
{ | ||
memset(spi_tx_packet_stop[i], 0, SPI_TOTAL_INDEX * 2); | ||
SPI_REG_u16(spi_tx_packet_stop[i], SPI_COMMAND_MODE) = SPI_SWAP_DATA_TX(1<<15, 16); | ||
} | ||
wifi_eth_tx_data.sensor_index = 0; | ||
wifi_eth_tx_data.packet_loss = 0; | ||
|
||
|
@@ -481,28 +502,8 @@ void wifi_eth_receive_cb(uint8_t src_mac[6], uint8_t *data, int len, char eth_or | |
command_index_prev = packet_recv->command_index - 1; | ||
} | ||
|
||
/* Prepare SPI packets */ | ||
uint16_t(*to_fill)[SPI_TOTAL_LEN] = spi_use_a ? spi_tx_packet_b : spi_tx_packet_a; | ||
|
||
for (int i = 0; i < CONFIG_N_SLAVES; i++) | ||
{ | ||
if (!TEST_BIT(spi_connected, i) && !spi_autodetect) | ||
continue; // ignoring this slave if it is not connected | ||
|
||
SPI_REG_u16(to_fill[i], SPI_COMMAND_MODE) = SPI_SWAP_DATA_TX(packet_recv->command[i].mode, 16); | ||
SPI_REG_32(to_fill[i], SPI_COMMAND_POS_1) = SPI_SWAP_DATA_TX(packet_recv->command[i].position[0], 32); | ||
SPI_REG_32(to_fill[i], SPI_COMMAND_POS_2) = SPI_SWAP_DATA_TX(packet_recv->command[i].position[1], 32); | ||
SPI_REG_16(to_fill[i], SPI_COMMAND_VEL_1) = SPI_SWAP_DATA_TX(packet_recv->command[i].velocity[0], 16); | ||
SPI_REG_16(to_fill[i], SPI_COMMAND_VEL_2) = SPI_SWAP_DATA_TX(packet_recv->command[i].velocity[1], 16); | ||
SPI_REG_16(to_fill[i], SPI_COMMAND_IQ_1) = SPI_SWAP_DATA_TX(packet_recv->command[i].current[0], 16); | ||
SPI_REG_16(to_fill[i], SPI_COMMAND_IQ_2) = SPI_SWAP_DATA_TX(packet_recv->command[i].current[1], 16); | ||
SPI_REG_u16(to_fill[i], SPI_COMMAND_KP_1) = SPI_SWAP_DATA_TX(packet_recv->command[i].kp[0], 16); | ||
SPI_REG_u16(to_fill[i], SPI_COMMAND_KP_2) = SPI_SWAP_DATA_TX(packet_recv->command[i].kp[1], 16); | ||
SPI_REG_u16(to_fill[i], SPI_COMMAND_KD_1) = SPI_SWAP_DATA_TX(packet_recv->command[i].kd[0], 16); | ||
SPI_REG_u16(to_fill[i], SPI_COMMAND_KD_2) = SPI_SWAP_DATA_TX(packet_recv->command[i].kd[1], 16); | ||
SPI_REG_u16(to_fill[i], SPI_COMMAND_ISAT_12) = SPI_SWAP_DATA_TX(packet_recv->command[i].isat, 16); | ||
} | ||
spi_use_a = !spi_use_a; | ||
/* Write command message in a RTOS mailbox for thread safe comunication */ | ||
xQueueOverwrite( wifi_eth_rx_cmd_mailbox, packet_recv ); | ||
|
||
/* Compute data for next wifi_eth_sensor packet */ | ||
wifi_eth_tx_data.packet_loss += ((struct wifi_eth_packet_command *)data)->command_index - command_index_prev - 1; | ||
|
@@ -515,7 +516,6 @@ void wifi_eth_receive_cb(uint8_t src_mac[6], uint8_t *data, int len, char eth_or | |
} | ||
|
||
//function that will be called on a link state change | ||
|
||
void wifi_eth_link_state_cb(bool new_state) | ||
{ | ||
// In WAITING_FOR_INIT, we don't know if wifi or ethernet is used | ||
|
@@ -530,9 +530,10 @@ void wifi_eth_link_state_cb(bool new_state) | |
|
||
void app_main() | ||
{ | ||
|
||
uart_set_baudrate(UART_NUM_0, 2000000); | ||
nvs_flash_init(); | ||
|
||
wifi_eth_rx_cmd_mailbox = xQueueCreate( 1, sizeof(struct wifi_eth_packet_command)); | ||
ws2812_control_init(); //init the LEDs | ||
set_all_leds(0x0f0f0f); | ||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be some inconsistency in the indentation (some lines using tabs, some spaces). Might be good to clean this up with some auto-formatter.