2025-05-02 5:50 AM - edited 2025-05-02 7:59 AM
Hi, I've been trying to receive 5 bytes of data from a master MCU using SPI in slave mode.
I have a timeslot control signal, and on each falling edge of that signal, I need to receive 5 bytes from the master.
The timeslot control signal consists of one long pulse followed by 15 short pulses.
Exemple: i receive the data for timeslot 0 at the end of timeslot 15 and so on.
I want to start receiving data from the second cycle of the timeslot control signal, and stop at the end of that cycle,
so I can compare the received data with what I’m supposed to get.
the yellow signal is my timeslot control and the green is the duration of the HAL_TIM_PWM_PulseFinishedCallback
here is my code:
#define RX_BUFFER_SIZE 5
#define number_of_timeslot 16
uint8_t rx_all_data[number_of_timeslot][RX_BUFFER_SIZE];
volatile uint8_t reading_in_progress = 0;
volatile uint8_t g_index_ts = 1;
volatile uint8_t g_ready_to_listen = 0;
volatile uint8_t g_current_ts_index = 0;
volatile uint8_t g_current_cycle = 0;
volatile uint8_t read_data_finished = 0;
volatile int is_timeslots_readed[16] = {0};
uint16_t NumberOfTS_Cycles_to_Run = 2;// set to 0 for freerun.
g_TSC_Max_TimeSlotsToRun = 16;
g_TSC_Phases_To_Run = NumberOfTS_Cycles_to_Run!=0 ? 2*NumberOfTS_Cycles_to_Run : -1;
uint8_t g_expected_data[number_of_timeslot][RX_BUFFER_SIZE] = {
{0x35, 0x80, 0x00, 0x80, 0x00}, // TS0
{0x35, 0x00, 0x80, 0x80, 0x00}, // TS1
{0x35, 0x90, 0x10, 0x90, 0x10}, // TS2
{0x35, 0x10, 0x90, 0x10, 0x90}, // TS3
{0x35, 0xA0, 0x20, 0xA0, 0x20}, // TS4
{0x35, 0x20, 0xA0, 0x20, 0xA0}, // TS5
{0x35, 0xB0, 0x30, 0xB0, 0x30}, // TS6
{0x35, 0x30, 0xB0, 0x30, 0xB0}, // TS7
{0x35, 0xC0, 0x40, 0xC0, 0x40}, // TS8
{0x35, 0x40, 0xC0, 0x40, 0xC0}, // TS9
{0x35, 0xD0, 0x50, 0xD0, 0x50}, // TS10
{0x35, 0x50, 0xD0, 0x50, 0xDC}, // TS11
{0x35, 0xE0, 0x60, 0xE0, 0x60}, // TS12
{0x35, 0x60, 0xE0, 0x60, 0xE0}, // TS13
{0x35, 0xF0, 0x70, 0xF0, 0x70}, // TS14
{0x35, 0x70, 0xF0, 0x70, 0xF0} // TS15
};
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET); // for debug
g_index_ts++;
if (g_index_ts==g_TSC_Max_TimeSlotsToRun)
{
g_current_cycle++;
g_index_ts=0;
}
if (g_current_cycle==2 && g_index_ts==0)
{
g_ready_to_listen = 0;
read_data_finished = 1;
}
if (g_index_ts==0 && g_current_cycle==1)
{
g_ready_to_listen = 1;
}
if (g_current_cycle==1 && g_ready_to_listen && !reading_in_progress)
{
__HAL_SPI_CLEAR_OVRFLAG(&hspi1);
reading_in_progress = 1;
HAL_SPI_Receive_DMA(&hspi1, rx_all_data[g_index_ts], RX_BUFFER_SIZE);
__HAL_TIM_SET_COUNTER(&htim7, 0);
HAL_TIM_Base_Start_IT(&htim7); //POUR le timout de 3 us du dma
}
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); // for debug
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if( htim->Instance == TIM16)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
if( g_TSC_Phases_To_Run == 0 )
{
HAL_TIM_PWM_Stop_IT(htim, TIM_CHANNEL_1);
}
else
{
if(htim->Instance->RCR>0)
{
htim->Instance->RCR=0;
htim->Instance->CCR1=g_TSC_Long_High_Pulse_Duration-1;
}
else
{
htim->Instance->RCR=(g_TSC_Max_TimeSlotsToRun-1)-1;
htim->Instance->CCR1=g_TSC_Short_High_Pulse_Duration-1;
}
}
if( g_TSC_Phases_To_Run > 0 )
g_TSC_Phases_To_Run--;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
}
if (htim->Instance == TIM7)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
HAL_TIM_Base_Stop_IT(&htim7);
if (reading_in_progress)
{
HAL_SPI_DMAStop(&hspi1);
reading_in_progress = 0;
is_timeslots_readed[g_index_ts] = 0;
//memset(rx_all_data[g_index_ts], 0, RX_BUFFER_SIZE);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
HAL_TIM_Base_Stop_IT(&htim7);
is_timeslots_readed[g_index_ts]=1;
reading_in_progress = 0;
}
I put tim7 for the dma timeout (3 microseconds).
My problem is that:
when i put a breakpoint on read_data_finished = 1; and i have a free run PWM
the output is :
reading_in_progress volatile uint8_t 0 '\0'
g_index_ts volatile uint8_t 0 '\0'
g_current_cycle volatile uint8_t 2 '\002'
read_data_finished volatile uint8_t 0 '\0'
g_ready_to_listen volatile uint8_t 0 '\0'
rx_all_data uint8_t [16][5] 0x20000044 (Hex)
rx_all_data[0] uint8_t [5] 0x20000044 (Hex)
rx_all_data[0][0] uint8_t 0x0 (Hex)
rx_all_data[0][1] uint8_t 0x0 (Hex)
rx_all_data[0][2] uint8_t 0x0 (Hex)
rx_all_data[0][3] uint8_t 0x0 (Hex)
rx_all_data[0][4] uint8_t 0x0 (Hex)
rx_all_data[1] uint8_t [5] 0x20000049 (Hex)
rx_all_data[1][0] uint8_t 0x0 (Hex)
rx_all_data[1][1] uint8_t 0x0 (Hex)
rx_all_data[1][2] uint8_t 0x0 (Hex)
rx_all_data[1][3] uint8_t 0x0 (Hex)
rx_all_data[1][4] uint8_t 0x0 (Hex)
rx_all_data[2] uint8_t [5] 0x2000004e (Hex)
rx_all_data[2][0] uint8_t 0x0 (Hex)
rx_all_data[2][1] uint8_t 0x0 (Hex)
rx_all_data[2][2] uint8_t 0x0 (Hex)
rx_all_data[2][3] uint8_t 0x0 (Hex)
rx_all_data[2][4] uint8_t 0x0 (Hex)
rx_all_data[3] uint8_t [5] 0x20000053 (Hex)
rx_all_data[3][0] uint8_t 0x80 (Hex)
rx_all_data[3][1] uint8_t 0x0 (Hex)
rx_all_data[3][2] uint8_t 0x80 (Hex)
rx_all_data[3][3] uint8_t 0x35 (Hex)
rx_all_data[3][4] uint8_t 0x0 (Hex)
rx_all_data[4] uint8_t [5] 0x20000058 (Hex)
rx_all_data[4][0] uint8_t 0x0 (Hex)
rx_all_data[4][1] uint8_t 0x80 (Hex)
rx_all_data[4][2] uint8_t 0x35 (Hex)
rx_all_data[4][3] uint8_t 0x10 (Hex)
rx_all_data[4][4] uint8_t 0x0 (Hex)
rx_all_data[5] uint8_t [5] 0x2000005d (Hex)
rx_all_data[5][0] uint8_t 0x10 (Hex)
rx_all_data[5][1] uint8_t 0x90 (Hex)
rx_all_data[5][2] uint8_t 0x10 (Hex)
rx_all_data[5][3] uint8_t 0x35 (Hex)
rx_all_data[5][4] uint8_t 0xa0 (Hex)
rx_all_data[6] uint8_t [5] 0x20000062 (Hex)
rx_all_data[6][0] uint8_t 0x0 (Hex)
rx_all_data[6][1] uint8_t 0x0 (Hex)
rx_all_data[6][2] uint8_t 0x0 (Hex)
rx_all_data[6][3] uint8_t 0x0 (Hex)
rx_all_data[6][4] uint8_t 0x0 (Hex)
rx_all_data[7] uint8_t [5] 0x20000067 (Hex)
rx_all_data[7][0] uint8_t 0xa0 (Hex)
rx_all_data[7][1] uint8_t 0x20 (Hex)
rx_all_data[7][2] uint8_t 0x35 (Hex)
rx_all_data[7][3] uint8_t 0x20 (Hex)
rx_all_data[7][4] uint8_t 0x0 (Hex)
rx_all_data[8] uint8_t [5] 0x2000006c (Hex)
rx_all_data[8][0] uint8_t 0xb0 (Hex)
rx_all_data[8][1] uint8_t 0x30 (Hex)
rx_all_data[8][2] uint8_t 0xb0 (Hex)
rx_all_data[8][3] uint8_t 0x0 (Hex)
rx_all_data[8][4] uint8_t 0x0 (Hex)
rx_all_data[9] uint8_t [5] 0x20000071 (Hex)
rx_all_data[9][0] uint8_t 0x30 (Hex)
rx_all_data[9][1] uint8_t 0xb0 (Hex)
rx_all_data[9][2] uint8_t 0x30 (Hex)
rx_all_data[9][3] uint8_t 0x35 (Hex)
rx_all_data[9][4] uint8_t 0xc0 (Hex)
rx_all_data[10] uint8_t [5] 0x20000076 (Hex)
rx_all_data[10][0] uint8_t 0x0 (Hex)
rx_all_data[10][1] uint8_t 0x0 (Hex)
rx_all_data[10][2] uint8_t 0x0 (Hex)
rx_all_data[10][3] uint8_t 0x0 (Hex)
rx_all_data[10][4] uint8_t 0x0 (Hex)
rx_all_data[11] uint8_t [5] 0x2000007b (Hex)
rx_all_data[11][0] uint8_t 0xc0 (Hex)
rx_all_data[11][1] uint8_t 0x40 (Hex)
rx_all_data[11][2] uint8_t 0x35 (Hex)
rx_all_data[11][3] uint8_t 0x40 (Hex)
rx_all_data[11][4] uint8_t 0x0 (Hex)
rx_all_data[12] uint8_t [5] 0x20000080 (Hex)
rx_all_data[12][0] uint8_t 0xd0 (Hex)
rx_all_data[12][1] uint8_t 0x50 (Hex)
rx_all_data[12][2] uint8_t 0xd0 (Hex)
rx_all_data[12][3] uint8_t 0x0 (Hex)
rx_all_data[12][4] uint8_t 0x0 (Hex)
rx_all_data[13] uint8_t [5] 0x20000085 (Hex)
rx_all_data[13][0] uint8_t 0x50 (Hex)
rx_all_data[13][1] uint8_t 0xd0 (Hex)
rx_all_data[13][2] uint8_t 0x50 (Hex)
rx_all_data[13][3] uint8_t 0x35 (Hex)
rx_all_data[13][4] uint8_t 0xe0 (Hex)
rx_all_data[14] uint8_t [5] 0x2000008a (Hex)
rx_all_data[14][0] uint8_t 0x0 (Hex)
rx_all_data[14][1] uint8_t 0x0 (Hex)
rx_all_data[14][2] uint8_t 0x0 (Hex)
rx_all_data[14][3] uint8_t 0x0 (Hex)
rx_all_data[14][4] uint8_t 0x0 (Hex)
rx_all_data[15] uint8_t [5] 0x2000008f (Hex)
rx_all_data[15][0] uint8_t 0xe0 (Hex)
rx_all_data[15][1] uint8_t 0x60 (Hex)
rx_all_data[15][2] uint8_t 0x35 (Hex)
rx_all_data[15][3] uint8_t 0x60 (Hex)
rx_all_data[15][4] uint8_t 0x0 (Hex)
is_timeslots_readed volatile int [16] 0x20000098 <is_timeslots_readed>
is_timeslots_readed[0] volatile int 0
is_timeslots_readed[1] volatile int 0
is_timeslots_readed[2] volatile int 0
is_timeslots_readed[3] volatile int 1
is_timeslots_readed[4] volatile int 0
is_timeslots_readed[5] volatile int 0
is_timeslots_readed[6] volatile int 0
is_timeslots_readed[7] volatile int 0
is_timeslots_readed[8] volatile int 0
is_timeslots_readed[9] volatile int 0
is_timeslots_readed[10] volatile int 1
is_timeslots_readed[11] volatile int 0
is_timeslots_readed[12] volatile int 0
is_timeslots_readed[13] volatile int 0
is_timeslots_readed[14] volatile int 1
is_timeslots_readed[15] volatile int 0
Add new expression
how can i have is_timeslots_readed[15]=0 (that mean dma not finished) and
If i reset and i jumb again on that breakpoint i will probably have something different and when i put uint16_t NumberOfTS_Cycles_to_Run = 2, i have the same problem?
Is there something that did not do correctly?
2025-05-14 2:11 AM
Hello @okeycii and welcome to the community;
Which STM32L4 are you using?
Do you get the same issue when you start receiving data from the first cycle of the timeslot control signal?
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-05-14 6:29 AM - edited 2025-05-14 6:30 AM
Hello @KDJEM.1 thank you very much!
yes i do.
2025-05-14 7:29 AM
Hello @okeycii;
Which STM32L4 devices are you using? Is STM32L496?
What is the QSPI and SPI frequencies?
Try to increase the timeout.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.