Switching from HAL to LL complications
Good day,
I recently made a post about getting my SPI to a certain speed. Ive managed to get the core down but found out that HAL is way too slow for what I need. I thus switched to low-level drivers. Now using LL instead of hal, Im trying to do a simple transmit receive to my 24 bit SPI. While HAL used to work, I'm doing something wrong. me and my collegue can't put our fniger on it. Anyone here think they might be able to help figure it out? Code is added below. many thanks in advance!
Board is the STM32 H755ZIQ.
Also before this comes up, yes I will likely have to do this through DMA eventually. This will have to do for now though.
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
LL_SPI_InitTypeDef SPI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOG);
/**SPI1 GPIO Configuration
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
PG11 ------> SPI1_SCK
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/* SPI1 interrupt Init */
NVIC_SetPriority(SPI1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_24BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 0x0;
LL_SPI_Init(SPI1, &SPI_InitStruct);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_SetFIFOThreshold(SPI1, LL_SPI_FIFO_TH_01DATA);
LL_SPI_DisableNSSPulseMgt(SPI1);
LL_SPI_Enable(SPI1);
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
void SPI1_TransmitReceive() {
while (LL_SPI_IsActiveFlag_TXP(SPI1) == 0); // Wait until the TX FIFO is not full (TXP)
LL_SPI_TransmitData8(SPI1, (TxData >> 16) & 0xFF); // MSB
while (LL_SPI_IsActiveFlag_TXP(SPI1) == 0); // Wait until the TX FIFO is not full (TXP)
LL_SPI_TransmitData8(SPI1, (TxData >> & 0xFF); // Middle byte
while (LL_SPI_IsActiveFlag_TXP(SPI1) == 0); // Wait until the TX FIFO is not full (TXP)
LL_SPI_TransmitData8(SPI1, TxData & 0xFF); // LSB
// Ensure all bytes are transmitted before reading RX
while (!LL_SPI_IsActiveFlag_EOT(SPI1)); // End Of Transfer flag
// Wait until we have three bytes in RX FIFO
while (LL_SPI_GetRxFIFOPackingLevel(SPI1) < 3);
uint32_t receivedData = 0;
while (LL_SPI_GetRxFIFOPackingLevel(SPI1) == 0);
receivedData |= (LL_SPI_ReceiveData8(SPI1) << 16); // MSB
while (LL_SPI_GetRxFIFOPackingLevel(SPI1) == 0);
receivedData |= (LL_SPI_ReceiveData8(SPI1) << 8); // Middle byte
while (LL_SPI_GetRxFIFOPackingLevel(SPI1) == 0);
receivedData |= LL_SPI_ReceiveData8(SPI1); // LSB
RxData = receivedData;
HAL_Delay(10); // Remove this delay in real-time applications
}
/* Stop TIM1 */
void Stop_TIM1(void)
{
/* Stop TIM1 base timer */
if (HAL_TIM_Base_Stop_IT(&htim1) != HAL_OK)
{
/* Error Handling */
Error_Handler();
}
}
/* Start TIM1 in interrupt mode */
void Start_TIM1(void)
{
HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
sampling = 1;
/* Start TIM1 base timer with interrupt */
if (HAL_TIM_Base_Start_IT(&htim1) != HAL_OK)
{
/* Error Handling */
Error_Handler();
}
}
void TIM1_UP_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim1);
}
///* Timer Interrupt Handler */
//void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
//{
// if (htim->Instance == TIM1) // Check if TIM1 triggered the interrupt
// {
// /* Code to execute on every timer interrupt */
// // This code should be executed every time TIM2 period elapses
// countertest++;
// four = 4; // This should set 'four' to 4 every time the timer triggers
// }
//}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
countertest++;
four = 4;
if (htim->Instance == TIM1) {
if (sampleIterator >= maxIterator) {
sampleIterator = 0;
}
currentSample++;
// Select SPI transfer data
TxData = txDataList[sampleIterator];
// Toggle CNV to trigger ADC conversion
GPIOC->BSRR = GPIO_BSRR_BS10; // Set CNV (pin 10 high)
GPIOC->BSRR = GPIO_BSRR_BR10; // Reset CNV (pin 10 low)
// Wait until C11 is low (ADC ready)
while (GPIOC->IDR & GPIO_IDR_ID11);
// Pull CS low
GPIOC->BSRR = GPIO_BSRR_BR12;
// Perform SPI transfer
//HAL_SPI_TransmitReceive(&hspi1, (uint32_t*) &TxData, (uint32_t*) &RxData, 1, HAL_MAX_DELAY);
SPI1_TransmitReceive();
// Pull CS high
GPIOC->BSRR = GPIO_BSRR_BS12;
// Extract 18-bit ADC value
adc_value = (RxData >> 6) & 0x3FFFF;
// Store data in active buffer
currentBuffer[bufferIndex++] = adc_value & 0xFF; // LSB
currentBuffer[bufferIndex++] = (adc_value >> 8) & 0xFF; // Middle byte
currentBuffer[bufferIndex++] = (adc_value >> 16) & 0xFF;// MSB
// When buffer is full, switch buffers and send data
if (bufferIndex >= BUFFER_SIZE) {
bufferIndex = 0;
if (!sendingInProgress) {
sendingInProgress = 1;
uint8_t* temp = currentBuffer;
currentBuffer = sendingBuffer;
sendingBuffer = temp;
CDC_Transmit_HS((uint8_t*)sendingBuffer, BUFFER_SIZE);
}
}
if (currentSample >= totalSamples) {
sampling = 0;
}
sampleIterator++;
}
}
