Skip to main content
Visitor II
January 13, 2020
Question

SPI too slow

  • January 13, 2020
  • 6 replies
  • 8260 views

Hi,

I am using SPI on STM32H74II MCU

First I am using a software NSS and not a Hardware NSS because it doesn't work.

I need to transmit 1 byte and receive 1 byte, the two commands one after another see the simple code below :

 RFID_SS_ENABLE;
 
 status = HAL_SPI_Transmit(&hspi3, buffer, 1, 1);
 
 status = HAL_SPI_Receive(&hspi3, buffer, 1, 1);
 
 RFID_SS_DISABLE;

I am monitoring the SPI lines by a scope and I monitor 900 us between the NSS enable and the MISO data.

I need all this to run and end in sub 30 us.

what I can do to run this simple code in the required timing ?

Best regards

Jawad Khaleel

    This topic has been closed for replies.

    6 replies

    Visitor II
    January 13, 2020

    If you need strict timings, you should read and write directly to the SPI data register and not use any HAL function calls.

    //pseudo code
     
    SPI->DATAREGISTER = "byte to send here";
    Poll status register, so you know when transmit/receive is done.
    "some variable to store received byte" = SPI->DATAREGISTER

    In the end the proplem might be somewhere else, than those lines of code.

    JKhalAuthor
    Visitor II
    January 14, 2020

    Hi,

    Thanks for your reply.

    Do you have an example code of using SPI registers for transmit and receive !?

    Best Regards

    Jawad Khaleel

    Graduate II
    January 13, 2020

    What speed are you clocking the bus at?

    Couldn't you use the HAL_SPI_TransmitReceive() variant and specify a slightly bigger buffer?

    Visitor II
    January 13, 2020

    SPI isn't slow. HAL is slow. Rule #1: You can have either strict timings or use HAL in a project, never both.

    Sending a byte using HAL on STM32F40690X00000BvvmKQAR.png

    Using the register interface

    0690X00000BvvmtQAB.png

    JKhalAuthor
    Visitor II
    January 14, 2020

    Hi,

    Thanks for your reply.

    Do you have an example code of using SPI registers for transmit and receive !?

    Best Regards

    Jawad Khaleel

    Visitor II
    January 15, 2020

    Do use 4 wire SPI method for transmit and receive. The master triggers the transaction by writing on the DR, and the transaction is complete when RXNE is set (but for a single byte, careful, I would write 32 bit which maybe the HW FIFO size for test).

    I am using the HAL to transfer big enough data chunks at 12 MHz over a meter so that the start/stop delay is becoming second order of annoyance.

    Visitor II
    September 29, 2020

    Hi JKhal,

    I had the same problem with incoming SPI data that is too fast for the “HAL_SPI_Receive(…)�?- function.

    Using direct SPI- register read, reduced the read- errors dramatically, but I still had some errors.

    After more research, I found the solution: You also need to instruct the compiler to optimise your SPI- read function for speed (“-Ofast�?)

    See attached code of my function…

    /**
     ******************************************************************************
     * >> GetTel - Function >>
     ******************************************************************************
     *
     * The incoming SPI data is very fast (6MHz clock), so we need to optimize
     * our code in order to read the data without error.
     *
     * The Get-Telemetry- Function is optimized in 2 ways :
     * ----------------------------------------------------
     * 1. The incoming data is read directly from the SPI- registers (SPI1->DR)
     *	 The "HAL_SPI_Receive(...)"- function is NOT used because it is too slow.
     * 2. Additionally the GCC - compiler needs to be instructed to optimize
     * the compiled code for maximum speed ("-Ofast")
     *
     * Notes:
     * * The Altitude- Telemetry- data- packet starts with an 'AC' - byte,
     * 	 and it is 37 bytes long.
     * * The Other- Telemetry- data- packet starts with an 'AA' - byte.
     * * I'm using SPI1
     * * You also need to Enable the SPI after initialization like this:
     * 	 __HAL_SPI_ENABLE(&hspi1);
     *
     ******************************************************************************
     */
    __attribute__((optimize("-Ofast"))) void GetTel(uint8_t StBy)
    {
    	do // Find the next Telemetry data packet
    	{
    		while ((SPI1->SR & SPI_FLAG_RXNE) == 0); //Wait for Data Ready
    		Tel_Rx[0] = SPI1->DR;	// Read Data Register Directly
    	} while (Tel_Rx[0] != StBy); // repeat until correct start byte is found
    	for (int x = 1; x < 37; x++) // Capture the rest of the Telemetry data packet
    	{
    		while ((SPI1->SR & SPI_FLAG_RXNE) == 0); // Wait for Data Ready
    		Tel_Rx[x] = SPI1->DR;	// Read Data Register Directly
    	} // for 1 to 36
    }

     Ok, so my application was for a “Receive Only Slave�? – SPI.

    You were asking for an example of Tx and Rx with SPI registers.

    The following code segment should give you an idea >>

    while (((SPI1->SR)&(SPI_FLAG_TXE)) == 0); //Wait for Tx buffer Empty before next Write
    SPI1->DR = TxByte;	//Write to Data Register Directly
    while (((SPI1->SR)&(SPI_FLAG_RXNE)) == 0); //Wait for Data Ready to Read
    RxByte = SPI1->DR;	//Read Data Register Directly

    Visitor II
    May 27, 2024

    hello @JElli.1 

    I'm using stm32h745. same issue I facing about spi timing. I want to read adc ads7046 this 12bit adc. I used different methods HAL_SPI_Receive(&hspi1, (uint8_t*)&ADC_Value1, 1, HAL_MAX_DELAY);

    HAL_SPI_Receive_IT(&hspi1, (uint8_t*)&ADC_Value1, 1);

    HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)&ADC_Value1, 1); 

    But spi is much slow. for polling it taking 5uS when controller clock 400mhz. and is bigger for IT, DMA...

    So as your post i want to read direst data register. but i got folloeing errors.

    dplogiic_0-1716789290213.png

    So instead of DR i used RXDR then error solve but output not getting . sclk and cs also not generated means code block at while (( spi1--> sr  line no.170. if i comment line170 to 174 then sclk generated properly

    dplogiic_1-1716789391973.png

    I used setting in stm32cubeide about pin declaration and mode setting, presclare clock and used code generated by stm32cube code generator. so please can you help me where i wrong. i want receive only master. 

    I need to set pins, mode, clock , presclare all also with register?    Please any example code you have then please can you

    /* USER CODE BEGIN Header */
    /**
     ******************************************************************************
     * @file : main.c
     * @brief : Main program body
     ******************************************************************************
     * @attention
     *
     * Copyright (c) 2024 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 */
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    #ifdef __GNUC__
    /* With GCC, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif /* __GNUC__ */
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    
    #ifndef HSEM_ID_0
    #define HSEM_ID_0 (0U) /* HW semaphore 0*/
    #endif
    
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    SPI_HandleTypeDef hspi1;
    DMA_HandleTypeDef hdma_spi1_rx;
    
    TIM_HandleTypeDef htim2;
    
    UART_HandleTypeDef huart3;
    
    /* USER CODE BEGIN PV */
    uint16_t AxBuf[5]; // Larger buffer to accommodate continuous data
    volatile uint8_t completed1 = 0;
    /* 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_USART3_UART_Init(void);
    static void MX_SPI1_Init(void);
    static void MX_TIM2_Init(void);
    /* USER CODE BEGIN PFP */
    
    /* 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 */
    /* USER CODE BEGIN Boot_Mode_Sequence_0 */
     int32_t timeout;
    /* USER CODE END Boot_Mode_Sequence_0 */
    
    /* USER CODE BEGIN Boot_Mode_Sequence_1 */
     /* Wait until CPU2 boots and enters in stop mode or timeout*/
     timeout = 0xFFFF;
     while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
     if ( timeout < 0 )
     {
     Error_Handler();
     }
    /* USER CODE END Boot_Mode_Sequence_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 Boot_Mode_Sequence_2 */
    /* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
    HSEM notification */
    /*HW semaphore Clock enable*/
    __HAL_RCC_HSEM_CLK_ENABLE();
    /*Take HSEM */
    HAL_HSEM_FastTake(HSEM_ID_0);
    /*Release HSEM in order to notify the CPU2(CM4)*/
    HAL_HSEM_Release(HSEM_ID_0,0);
    /* wait until CPU2 wakes up from stop mode */
    timeout = 0xFFFF;
    while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
    if ( timeout < 0 )
    {
    Error_Handler();
    }
    /* USER CODE END Boot_Mode_Sequence_2 */
    
     /* USER CODE BEGIN SysInit */
    
     /* USER CODE END SysInit */
    
     /* Initialize all configured peripherals */
     MX_GPIO_Init();
     MX_DMA_Init();
     MX_USART3_UART_Init();
     MX_SPI1_Init();
     MX_TIM2_Init();
     /* USER CODE BEGIN 2 */
    //uint16_t adcData=0;
     /* USER CODE END 2 */
    uint16_t adcData[2]; // Array to hold two 16-bit ADC data
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
     /* USER CODE END WHILE */
     ReadADC(adcData);
    
     // Process adcData[0] and adcData[1] as needed
    // printf("ADC Data 0: %d\n", adcData[0]);
    // printf("ADC Data 1: %d\n", adcData[1]);
     /* USER CODE BEGIN 3 */
     }
     /* USER CODE END 3 */
    }
    
    __attribute__((optimize("-Ofast"))) void ReadADC(uint16_t *adcData)
    {
     // Ensure SPI is enabled
     __HAL_SPI_ENABLE(&hspi1);
     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
     // Read ADC data
     while ((SPI1->SR & SPI_FLAG_RXNE) == 0); // Wait for RXNE flag
     adcData[0] = SPI1->RXDR; // Read first 16-bit word
    
     while ((SPI1->SR & SPI_FLAG_RXNE) == 0); // Wait for RXNE flag
     adcData[1] = SPI1->RXDR; // Read second 16-bit word
     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
     // Optional: Disable SPI after data transfer
     // __HAL_SPI_DISABLE(&hspi1);
    }
    /**
     * @brief System Clock Configuration
     * @retval None
     */
    void SystemClock_Config(void)
    {
     RCC_OscInitTypeDef RCC_OscInitStruct = {0};
     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
     /** Supply configuration update enable
     */
     HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
    
     /** Configure the main internal regulator output voltage
     */
     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
     while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
    
     /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
     RCC_OscInitStruct.HSEState = RCC_HSE_ON;
     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
     RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
     RCC_OscInitStruct.PLL.PLLM = 1;
     RCC_OscInitStruct.PLL.PLLN = 100;
     RCC_OscInitStruct.PLL.PLLP = 2;
     RCC_OscInitStruct.PLL.PLLQ = 4;
     RCC_OscInitStruct.PLL.PLLR = 2;
     RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
     RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
     RCC_OscInitStruct.PLL.PLLFRACN = 0;
     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_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
     RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
     RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
     RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
     RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
     RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
     RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
    
     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
     {
     Error_Handler();
     }
    }
    
    /**
     * @brief SPI1 Initialization Function
     * @param None
     * @retval None
     */
    static void MX_SPI1_Init(void)
    {
    
     /* USER CODE BEGIN SPI1_Init 0 */
    
     /* 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_RXONLY;
     hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
     hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
     hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
     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 = 0x0;
     hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
     hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
     hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
     hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
     hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
     hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
     hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
     hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
     hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
     hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
     if (HAL_SPI_Init(&hspi1) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN SPI1_Init 2 */
    
     /* USER CODE END SPI1_Init 2 */
    
    }
    
    /**
     * @brief TIM2 Initialization Function
     * @param None
     * @retval None
     */
    static void MX_TIM2_Init(void)
    {
    
     /* USER CODE BEGIN TIM2_Init 0 */
    
     /* USER CODE END TIM2_Init 0 */
    
     TIM_ClockConfigTypeDef sClockSourceConfig = {0};
     TIM_MasterConfigTypeDef sMasterConfig = {0};
    
     /* USER CODE BEGIN TIM2_Init 1 */
    
     /* USER CODE END TIM2_Init 1 */
     htim2.Instance = TIM2;
     htim2.Init.Prescaler = 0;
     htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
     htim2.Init.Period = 0xffff-1;
     htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
     htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
     if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
     {
     Error_Handler();
     }
     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
     if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
     {
     Error_Handler();
     }
     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
     if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN TIM2_Init 2 */
    
     /* USER CODE END TIM2_Init 2 */
    
    }
    
    /**
     * @brief USART3 Initialization Function
     * @param None
     * @retval None
     */
    static void MX_USART3_UART_Init(void)
    {
    
     /* USER CODE BEGIN USART3_Init 0 */
    
     /* USER CODE END USART3_Init 0 */
    
     /* USER CODE BEGIN USART3_Init 1 */
    
     /* USER CODE END USART3_Init 1 */
     huart3.Instance = USART3;
     huart3.Init.BaudRate = 115200;
     huart3.Init.WordLength = UART_WORDLENGTH_8B;
     huart3.Init.StopBits = UART_STOPBITS_1;
     huart3.Init.Parity = UART_PARITY_NONE;
     huart3.Init.Mode = UART_MODE_TX_RX;
     huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
     huart3.Init.OverSampling = UART_OVERSAMPLING_16;
     huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
     huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
     huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
     if (HAL_UART_Init(&huart3) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN USART3_Init 2 */
    
     /* USER CODE END USART3_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_Stream0_IRQn interrupt configuration */
     HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
     HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
    
    }
    
    /**
     * @brief GPIO Initialization Function
     * @param 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_GPIOD_CLK_ENABLE();
    
     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
    
     /*Configure GPIO pin : PD14 */
     GPIO_InitStruct.Pin = GPIO_PIN_14;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
    /* USER CODE BEGIN MX_GPIO_Init_2 */
    /* USER CODE END MX_GPIO_Init_2 */
    }
    
    /* USER CODE BEGIN 4 */
    PUTCHAR_PROTOTYPE
    {
    	/* Place your implementation of fputc here */
    	/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
    	HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
    
    	return ch;
    }
    /* 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.
     * @param file: pointer to the source file name
     * @param 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 */

    share?

    Graduate II
    May 27, 2024

    Reduce the prescaler to make it clock faster.

    Move more than a single word to get any bandwidth advantages.