Skip to main content
Vitor Schulter
Associate II
August 15, 2018
Question

STATE SPI READY - HAL Driver

  • August 15, 2018
  • 9 replies
  • 3423 views

Hello,

I am working on a code that uses the HAL library for SPI communication. But I have a problem with SPI's state-checking routine.

void libera_escrita(void)

{

SPI_TxBuffer[0] = 6;

HAL_GPIO_WritePin(GPIOC, CS_Pin, GPIO_PIN_RESET);

while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t*)SPI_TxBuffer, (uint8_t *)SPI_RxBuffer, 1);

while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

HAL_GPIO_WritePin(GPIOC, CS_Pin, GPIO_PIN_SET);

}

My code stays in that while, what could be causing this?

    This topic has been closed for replies.

    9 replies

    T J
    Senior III
    August 15, 2018

    You shouldn't be using the HAL_SPI_TransmitReceive_IT(),

    I dont bother to DMA the SPI since I am not streaming data like Audio

    I use these routines without issue:

    void transfer(unsigned short data) {
     char RxSPI;
     
     while (!(hspi1.Instance->SR & SPI_FLAG_TXE)) ; // wait while not empty
     *((__IO uint8_t *)&hspi1.Instance->DR) = data; // send datat here
     RxSPI = hspi1.Instance->DR;// + readSPI_SR; // read Rx byte and discard, only clearing the buffer
    }
    char transfer_receive(unsigned short data) {
     
     char RxSPI; 
     while(!(hspi1.Instance->SR & SPI_FLAG_TXE))
     ;
     while ((hspi1.Instance->SR & SPI_FLAG_RXNE)) // load all the bytes received, only keep the last one
     RxSPI = hspi1.Instance->DR; //empty fifo
     
     *((__IO uint8_t *)&hspi1.Instance->DR) = data; // force the SPI to transceive 8 bit
     while(!(hspi1.Instance->SR & SPI_FLAG_TXE)) // wait to transmitter double buffer to shift into transmitter
     ; 
     while ((hspi1.Instance->SR & SPI_FLAG_BSY)) ; // wait for data to shift out of the processor pins
     while((hspi1.Instance->SR & SPI_FLAG_RXNE)) // load all the bytes received, only keep the last one
     RxSPI = hspi1.Instance->DR; // we only want the last byte
     
     return RxSPI;
    }

    like this:

    void eraseSector(char command, uint32_t address){
     enableFlashWrites();
     
     
     // command should be BlockErase4k, or BlockErase12k or ChipErase
     HAL_GPIO_WritePin(AT25DN256_nSS_GPIO_Port, AT25DN256_nSS_Pin, GPIO_PIN_RESET); 
     transfer(command); 
     char addressByte2 = (address >> 16) & 0xff;
     char addressByte1 = (address >> 8) & 0xff;
     char addressByte0 = (address) & 0xff;
     
     char dummyByte = 0;
     transfer(addressByte2);
     transfer(addressByte1);
     transfer_receive(addressByte0);
     
     
     HAL_GPIO_WritePin(AT25DN256_nSS_GPIO_Port, AT25DN256_nSS_Pin, GPIO_PIN_SET); 
     // erase should start now 
    }

    and something a little more detailed :

    void readFlashBytes(uint32_t address, int length, char*ptr){
     
     int flashStatus1 = readFlashCommand(ReadStatusByte); 
     int flashStatus2 = readFlashCommand(ReadStatusByte2); 
     
     // printf(string, "Flash Status bytes %02x", flashStatus1); 
     
     while((flashStatus1 & 0x01)) {
     // busy not ready
     checkBackgroundServices(); // this checks the Uart DMAs progress " OS services" 
     flashStatus1 = readFlashCommand(ReadStatusByte);
     } 
     
     HAL_GPIO_WritePin(AT25DN256_nSS_GPIO_Port, AT25DN256_nSS_Pin, GPIO_PIN_RESET);
     
     transfer(ReadFlashByte);
     char addressByte2 = (address >> 16) & 0xff;
     char addressByte1 = (address >> 8) & 0xff;
     char addressByte0 = (address) & 0xff;
     
     char dummyByte = 0;
     transfer(addressByte2);
     transfer(addressByte1);
     transfer(addressByte0);
     
     while (length--)
     { 
     *ptr = transfer_receive(dummyByte);
     ptr++;
     } 
     HAL_GPIO_WritePin(AT25DN256_nSS_GPIO_Port, AT25DN256_nSS_Pin, GPIO_PIN_SET); 
    }

    Vitor Schulter
    Associate II
    August 16, 2018

    Hello thank you for the answer

    I used the routine you suggested, but it seems I still have the same problem. When executing the following line

    while (! (hspi1.Instance-> SR & SPI_FLAG_TXE));

    The code is locked on this line.

    Peter Mather
    Associate III
    August 16, 2018

    Are you sure you have the relevant clocks running? Have a look at the SPI examples in CubeMX

    T J
    Senior III
    August 16, 2018

    I use this to initialise ...

    void CAN_Config() {
     CAN_FilterConfTypeDef sFilterConfig;
     static CanTxMsgTypeDef TxMessage;
     static CanRxMsgTypeDef RxMessage;
     
     //##-1- Configure the CAN peripheral #######################################
     hcan.pTxMsg = &TxMessage;
     hcan.pRxMsg = &RxMessage;
     
     hcan.pTxMsg->RTR	 	= CAN_RTR_DATA;
     hcan.pTxMsg->DLC	 	= 8; 		
     hcan.pTxMsg->StdId	 	= 0x101; 	
     hcan.pTxMsg->ExtId	 	= 0x102; 	
    	
     hcan.pRxMsg->DLC	 	= 8; 	
     hcan.pRxMsg->StdId	 	= 0x101; 	
     hcan.pRxMsg->ExtId	 	= 0x102; 	 		
     hcan.pRxMsg->RTR	 	= CAN_RTR_DATA; 						
     
     if(HAL_CAN_Init(&hcan) != HAL_OK)
     {
     // Initiliazation Error 
     _Error_Handler(__FILE__, __LINE__);
     }
     
     //##-2- Configure the CAN Filter ###########################################
     sFilterConfig.FilterNumber 					= 0;
     sFilterConfig.FilterMode 					= CAN_FILTERMODE_IDMASK;
     sFilterConfig.FilterScale 					= CAN_FILTERSCALE_32BIT;
     sFilterConfig.FilterIdHigh 					= 0x400 << 5; //11-bit ID in top bits
     sFilterConfig.FilterIdLow 					= 0x0000;
     sFilterConfig.FilterMaskIdHigh	 	 = 0x600 << 5; 	// resolves as 0x0400 - 0x05FF
     sFilterConfig.FilterMaskIdLow				= 0x0000;
     sFilterConfig.FilterFIFOAssignment	 = 0;
     sFilterConfig.FilterActivation	 = ENABLE;
     sFilterConfig.BankNumber 	 			= 0;
     
     if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
     {
     // Filter configuration Error 
     _Error_Handler(__FILE__, __LINE__);
     char string[38];
     
     sprintf( string, "Can Filter configuration Error\n\r");
     puts1( string);
     }
     
     //##-2- Configure the 2nd CAN Filter ###########################################
     sFilterConfig.FilterNumber 			= 1;
     sFilterConfig.FilterMode 			= CAN_FILTERMODE_IDMASK;
     sFilterConfig.FilterScale 			= CAN_FILTERSCALE_32BIT;
     sFilterConfig.FilterIdHigh 			= 0x600 << 5; //11-bit ID in top bits		// command channel
     sFilterConfig.FilterIdLow 			= 0x0000;
     sFilterConfig.FilterMaskIdHigh		= 0x700 << 5; 	// resolves as 0x0600 - 0x06FF
     sFilterConfig.FilterMaskIdLow		= 0x0000;
     sFilterConfig.FilterFIFOAssignment	= 1;
     sFilterConfig.FilterActivation		= ENABLE;
     sFilterConfig.BankNumber 			= 1;
     
     if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
     {
     // Filter configuration Error 
     _Error_Handler(__FILE__, __LINE__);
     char string[38];
     sprintf( string, "Can Filter configuration Error\n\r");
     puts1( string);
     }
     
    }

    thats wrapped in my own CanStartup routine.

    void initCairoCan(void) {
     CAN_Config();
     canRxpointerIN = 0;
     canRxMsgIN = 0;
     canRxMsgOUT = 0;
     canRxMsgTableEMPTY = true;
     canRxMsgTableFULL = false; 
     
     for (int i = 0; i < 16; i++)
     IOCanMsgFlag[i] = false;
     
    			
    	
     __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP1);
     __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP0);
    		
     canTxMsgIN = 0;
     canTxMsgOUT = 0;
     canTxMsgTableEMPTY 		= true;
     canTxMsgTableFULL 		= false;
     canTxMsgTableOverflow = false;
     canTxMsgOverrun = false;
     blockCanTx = false;
     
    }

    then it all works.

    Vitor Schulter
    Associate II
    August 17, 2018

    TJ, Is this routine that you sent is not for CAN protocol?

    T J
    Senior III
    August 17, 2018

    my bad, wrong post... :)

    Vitor Schulter
    Associate II
    August 22, 2018

    Hello, I still have the same problem. My code stops executing because the status of the SPI bus stays as:

     HAL_SPI_STATE_BUSY_TX_RX = 0x05U, / *! <Data Transmission and Reception process is ongoing * /

    Would anyone have any more suggestions?

    Vitor Schulter
    Associate II
    August 22, 2018

    I have now realized that the SPI problem is only caught after some data has been received by the UART

    T J
    Senior III
    August 22, 2018

    Did you find the issue ?