cancel
Showing results for 
Search instead for 
Did you mean: 

Nucleo L452RE SPI: 10us delay after CS going low before SPI SCK starts

ASRAJAWAT12
Visitor

Hi ST community,

I am facing an issue of 10us delay between CS line going low and SPI SCK start, when I am doing SPI communication with a slave device, which supports upto 15MHz SPI communication.

Below is the main.c file snippet for your reference. Please help in fixing the issue. I have also attached complete code file as well as the CRO capture of SPI comm for your ref. Thanks in advance!

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdint.h>
#include <string.h> // For memset

/* Private variables ---------------------------------------------------------*/

SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_tx;
DMA_HandleTypeDef hdma_spi1_rx;



// Global variable for the master's Gray Counter
volatile uint8_t header_gray_code = 0;

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;

TIM_HandleTypeDef htim16;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);
static void MX_TIM16_Init(void);
/* USER CODE BEGIN PFP */
// Define your Pins and Ports (assuming PA4=NSS, PA5=Red LED, PA9=LD2)
#define NSS_GPIO_PORT GPIOA
#define NSS_GPIO_PIN  GPIO_PIN_4
#define RED_LED_PORT  GPIOA
#define RED_LED_PIN   GPIO_PIN_5
#define LD2_GPIO_PORT GPIOA
#define LD2_PIN       GPIO_PIN_9

// Global Error Tracking Variables
#define MAX_CRC_ERRORS 1
static volatile uint8_t crc_error_count = 0;
static volatile uint8_t spi_communication_discarded = 0;

// Delay generation using TIM16
#define TIM16_PRESCALER  1 // Minimum delay generated = 1/(80M) = 12.5 ns


// Command Arguments
#define CMD_WRITE 0x00
#define CMD_READ  0x01

// Global Gray counter
static uint8_t Header_Counter = 0;

// Global DMA Buffers (6 bytes for 48-bit frame)
#define FRAME_SIZE_BYTES 6
static uint8_t tx_frame_buffer[FRAME_SIZE_BYTES];
static uint8_t rx_frame_buffer[FRAME_SIZE_BYTES];
volatile uint32_t sent_data_for_comparison = 0; // Data is now 32-bit

/* Custom CRC-6 Implementation */
#define CRC6_POLY  0x33 // 0x33 (0b110011)
#define CRC6_INIT  0x3F // 0x3F (0b111111)
#define CRC6_WIDTH 6
#define CRC_DATA_BITS 42 // 6 (Addr) + 2 (Cmd) + 2 (Hdr) + 32 (Data)

/**
* @brief Calculates the custom CRC-6 for a 42-bit input data.
*  data_42_bits The 42 bits of data to calculate CRC over, passed as uint64_t.
* @retval The 6-bit CRC value.
*/


uint8_t calculate_crc6(uint64_t data_42_bits) {
    const uint8_t POLYNOMIAL = 0x33;      //
    const uint8_t INITIAL_VALUE = 0x3F;   // 6-bit seed (binary 111111)

    uint8_t crc6 = INITIAL_VALUE;

   // Process each bit from MSB (bit 26) down to LSB (bit 0)
    for (int i = 41; i >= 0; i--) {
        uint8_t bit = (data_42_bits >> i) & 0x01;         // Extract the bit at position i
        uint8_t crcMsb = (crc6 >> 5) & 0x01;        // MSB of the 6-bit CRC

        // Shift left by 1 bit and keep CRC6 of 6 bits only
        crc6 = (crc6 << 1) & 0x3F;

        // XOR condition: If bit differs from CRC MSB
        if ((bit ^ crcMsb) != 0) {
        crc6 ^= POLYNOMIAL;
        crc6 &= INITIAL_VALUE;  // Ensure CRC6 holds last 6 bits
        }
    }

    return crc6;
}

uint8_t get_next_gray_code(void)

{

 // Gray counter logic remains the same (0, 1, 3, 2)

 uint8_t binary_counter = (Header_Counter + 1) % 4;

 Header_Counter = binary_counter;

 return Header_Counter ^ (Header_Counter >> 1);

}


/**
* @brief Constructs the 48-bit frame and serializes it into the 6-byte TX buffer (MSB first).
* Frame format (Bit 47 to Bit 0): [Addr(6)] [Cmd(2)] [Hdr(2)] [Data(32)] [CRC6(6)]
*/
void construct_spi_frame_8bit(uint8_t reg_address, uint8_t command_arg, uint32_t data_bits)
{
    uint64_t temp_frame_48bit = 0;
    uint64_t data_for_crc = 0;
    uint8_t header_gray_code = get_next_gray_code();

    // 1. Assemble the 42 data bits for CRC calculation (Bits 47 down to 6)
    // Addr (6 bits) -> Bits 47-42
    temp_frame_48bit |= ((uint64_t)(reg_address & 0x3F) << 42);

    // Cmd (2 bits) -> Bits 41-40
    temp_frame_48bit |= ((uint64_t)(command_arg & 0x03) << 40);

    // Hdr (2 bits) -> Bits 39-38
    temp_frame_48bit |= ((uint64_t)(header_gray_code & 0x03) << 38);

    // Data (32 bits) -> Bits 37-6
    temp_frame_48bit |= ((uint64_t)(data_bits & 0xFFFFFFFF) << 6);

    // Extract only 42 bits for CRC calculation (bits 47 down to 6)
       data_for_crc = (temp_frame_48bit >> 6) & ((1ULL << 42) - 1);

    // 3. Calculate CRC
    uint8_t crc_value = calculate_crc6(data_for_crc);

    // 4. Append CRC (6 bits) - Bit 5 down to 0
    temp_frame_48bit |= (uint64_t)(crc_value & 0x3F);

    // 5. Break the 48-bit frame into 6 bytes, MSB-first (Big-Endian)
    // The SPI master sends Byte 5 first (MSB)
    tx_frame_buffer[0] = (uint8_t)((temp_frame_48bit >> 40) & 0xFF); // Byte 5 (Bits 47-40)
    tx_frame_buffer[1] = (uint8_t)((temp_frame_48bit >> 32) & 0xFF); // Byte 4 (Bits 39-32)
    tx_frame_buffer[2] = (uint8_t)((temp_frame_48bit >> 24) & 0xFF); // Byte 3 (Bits 31-24)
    tx_frame_buffer[3] = (uint8_t)((temp_frame_48bit >> 16) & 0xFF); // Byte 2 (Bits 23-16)
    tx_frame_buffer[4] = (uint8_t)((temp_frame_48bit >> ‌‌ & 0xFF);  // Byte 1 (Bits 15-8)
    tx_frame_buffer[5] = (uint8_t)(temp_frame_48bit & 0xFF);        // Byte 0 (Bits 7-0)
}


/* MODIFIED Full-Duplex DMA Transfer Function ----------------------------------*/
HAL_StatusTypeDef spi_transmit_receive_dma_frame(uint8_t reg_address, uint8_t command_arg, uint32_t data_bits)
{
    if (spi_communication_discarded)
    {
        return HAL_ERROR;
    }

    if (reg_address >= 49) // Check for valid register address
      {
          return HAL_ERROR;
      }

    // 1. Store the 32-bit data for comparison
    sent_data_for_comparison = data_bits;

    // 2. Construct the 48-bit frame into the 8-bit TX buffer (6 bytes)
    construct_spi_frame_8bit(reg_address, command_arg, data_bits);

    // 3. Clear the RX buffer
    memset(rx_frame_buffer, 0, sizeof(rx_frame_buffer));

    // 4. Pull NSS low
    HAL_GPIO_WritePin(NSS_GPIO_PORT, NSS_GPIO_PIN, GPIO_PIN_RESET);
   // delay(3); //Delay equal to 12.5*3 = 37.5ns

    // 5. Initiate the Full-Duplex DMA transfer. Size is 6 bytes.
    HAL_StatusTypeDef status = HAL_SPI_TransmitReceive_DMA(
        &hspi1,
        tx_frame_buffer,
        rx_frame_buffer,
        FRAME_SIZE_BYTES); // Transfer 6 bytes

    return status;
}

/* DMA Callback Function (Success Path) - Logic remains similar -----------------*/
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi->Instance == SPI1)
    {
        // 1. Pull NSS high to end the transaction and insert a delay of 500ns
        HAL_GPIO_WritePin(NSS_GPIO_PORT, NSS_GPIO_PIN, GPIO_PIN_SET);


        // 2. Clear the red LED and reset error count on successful completion
        //HAL_GPIO_TogglePin(RED_LED_PORT, RED_LED_PIN);
        crc_error_count = 0;

//        // 3. Reconstruct the received 48-bit frame from 6 bytes (MSB first)
//        uint64_t received_frame_48bit = 0;
//
//        received_frame_48bit |= ((uint64_t)rx_frame_buffer[0] << 40);
//        received_frame_48bit |= ((uint64_t)rx_frame_buffer[1] << 32);
//        received_frame_48bit |= ((uint64_t)rx_frame_buffer[2] << 24);
//        received_frame_48bit |= ((uint64_t)rx_frame_buffer[3] << 16);
//        received_frame_48bit |= ((uint64_t)rx_frame_buffer[4] << 8);
//        received_frame_48bit |= rx_frame_buffer[5];
//
//        // 4. Extract the 32-bit data (Bits 37 down to 6)
//        uint32_t received_data = (uint32_t)((received_frame_48bit >> 6) & 0xFFFFFFFF);
//
//        // 5. Compare the sent data with the received data
//        if (received_data == sent_data_for_comparison)
//        {
//            // Data Match Action (e.g., toggle user LED for success)
//            HAL_GPIO_TogglePin(LD2_GPIO_PORT, LD2_PIN);
//        }
//
//        sent_data_for_comparison = 0;
    }
}


/* DMA Error Callback Function (Error Path) - Logic remains same ----------------*/
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi->Instance == SPI1)
    {
        if (hspi->ErrorCode & HAL_SPI_ERROR_CRC)
        {
            crc_error_count++;

            if (crc_error_count >= MAX_CRC_ERRORS)
            {
                spi_communication_discarded = 1;
            }
        }

       HAL_GPIO_WritePin(NSS_GPIO_PORT, NSS_GPIO_PIN, GPIO_PIN_SET);

        if (!spi_communication_discarded)
        {
             hspi->State = HAL_SPI_STATE_READY;
        }
    }
}


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_TIM16_Init();
  /* USER CODE BEGIN 2 */
  HAL_Delay(100);
  HAL_GPIO_WritePin(NSS_GPIO_PORT, NSS_GPIO_PIN, SET);
  HAL_GPIO_WritePin(RED_LED_PORT, RED_LED_PIN, RESET);

  // Test data (now 32-bit)
  uint8_t  reg_addr = 0x00; // Max 0x31 (decimal-49)
  uint32_t test_data = 0x10FF0F0F;

  uint8_t  dummy_tx[1] = {0xFF};
  uint8_t  dummy_rx[1] = {0x00};

  HAL_TIM_Base_Start(&htim16);

  // If using Hardware NSS:
  //HAL_SPI_TransmitReceive(&hspi1, dummy_tx, dummy_rx, 1, HAL_MAX_DELAY);

  // If using Software NSS:

  HAL_GPIO_WritePin(NSS_GPIO_PORT, NSS_GPIO_PIN, GPIO_PIN_RESET);
  HAL_SPI_TransmitReceive(&hspi1, dummy_tx, dummy_rx, 1,HAL_MAX_DELAY);

  HAL_GPIO_WritePin(NSS_GPIO_PORT, NSS_GPIO_PIN, GPIO_PIN_SET);



  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  if (!spi_communication_discarded)
     {
         if (HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_READY)
         {
             // Note: Data is 32-bit
             spi_transmit_receive_dma_frame(reg_addr, CMD_READ, test_data);
             delay(25); // delay of 312.5ns (Delay value is equal to (x*12.5)ns

         }

     }

  else
     {
         HAL_Delay(500);
         HAL_GPIO_TogglePin(RED_LED_PORT, RED_LED_PIN);
     }


    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 64;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 10;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief SPI1 Initialization Function
  *  None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

// Mode 3 device : CPOL =1 (Idle High), CPHA = 1 (Rising edge data acquisition)

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief TIM16 Initialization Function
  *  None
  * @retval None
  */
static void MX_TIM16_Init(void)
{

  /* USER CODE BEGIN TIM16_Init 0 */

  /* USER CODE END TIM16_Init 0 */

  /* USER CODE BEGIN TIM16_Init 1 */

  /* USER CODE END TIM16_Init 1 */
  htim16.Instance = TIM16;
  htim16.Init.Prescaler = 20-1;
  htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim16.Init.Period = 65535;
  htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim16.Init.RepetitionCounter = 0;
  htim16.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim16) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM16_Init 2 */

  /* USER CODE END TIM16_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);

}

/**
  * @brief GPIO Initialization Function
  *  None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5|GPIO_PIN_9, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PA5 PA9 */
  GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
// This function will generate a delay equal to (0.25* quarter_us)
void delay(uint16_t quarter_us)
{
    __HAL_TIM_SET_COUNTER(&htim16, 0);
while(__HAL_TIM_GET_COUNTER(&htim16)< quarter_us);
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  *   file: pointer to the source file name
  *   line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Edited to apply source code formatting - please see How to insert source code for future reference.

10 REPLIES 10
TDK
Super User

HAL_SPI_TransmitReceive_DMA is a heavy function as it has to initialize everything. 10us is a reasonable expectation here.

Make your own SPI code if you need faster execution, or use Release mode, or faster clock speeds.

 

There's no way to have the NSS line be handled directly by the SPI peripheral so that it is low only for the transaction on the STM32L4xx family. This is an option on newer STM32 families, such as the STM32H7.

If you feel a post has answered your question, please click "Accept as Solution".

I used 80MHz clock speed, which is maximum for this MCU. Also I tried the similar code using LL drivers instead of HAL but still the issue remained the same.

What optimisation level are you using?

Have you tried increasing it?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

I haven't used any optimizations in the code. My slave device needs not more than 300ns delay between CS enable and SPI SCK start.

Will using compiler and linker optimisations help in fixing these delay?

Also, since we need to show the demo within next week before finalizing the MCU part number. That's why I used HAL APIs for quick testing with slave device, rather than writing my own SPI drivers.


@ASRAJAWAT12 wrote:

I haven't used any optimizations in the code.


So try it, then!

As @TDK said, the delay you're seeing on the order of what would be expected, considering what the code is doing.

You don't necessarily need to re-write the entire HAL driver - you may be able to just tweak it to your needs...

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
TDK
Super User

What device are you interfacing with?

If you feel a post has answered your question, please click "Accept as Solution".
I am using position sensor device as a slave

Provide the part number.

If you feel a post has answered your question, please click "Accept as Solution".