cancel
Showing results for 
Search instead for 
Did you mean: 

STATE SPI READY - HAL Driver

Vitor Schulter
Associate II

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?

9 REPLIES 9
T J
Lead

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

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

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

T J
Lead

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

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

T J
Lead

my bad, wrong post... 🙂

Vitor Schulter
Associate II

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

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

T J
Lead

Did you find the issue ?