cancel
Showing results for 
Search instead for 
Did you mean: 

Optimization breaks SPI code on L562

L562 processor.  SPI1.  Blocking mode.  Two sequential writes, second write variably returns error.

code:

// uses CS if USE_CS is set to CS_ACTIVE (default)
// CS is not used if USE_CS is set to CS_INACTIVE

uint32_t HAL_SPI::Send(
						uint8_t* cmdptr,
						uint32_t  cmd_count,
						uint8_t* dataptr,
						uint32_t  data_count,
						bool USE_CS,
						enum SPI_TRANSFER_MODE Override)
{

	enum SPI_TRANSFER_MODE		NEW_mode = OUT_mode;
	int							error_code;

//	int							old_divisor;

	// ********************************** check input parameters***********************************
	// need to check overrides
	switch (Override)
	{
		case SPI_DMA:			// TRANSMIT IS DMA FROM BUFFER, RECEIVE IS IRQ QUEUE (MAY CHANGE)
		case SPI_IRQ:			// TRANSMIT IS IRQ DRIVEN
		case SPI_BLOCKING:		// TRANSMIT AND RECEIVE ARE BYTE BLOCKING
		{
			NEW_mode = Override;
			break;
		}
		default:
		{
			NEW_mode = OUT_mode;
			// leave mode as is, cannot override
		}
	}

	switch (NEW_mode)
	{
		case SPI_BLOCKING:		// TRANSMIT AND RECEIVE ARE BYTE BLOCKING
		{
			time_start = _MICROSECOND_TIMER.Instance->CNT;
			// always semaphore protected
			if (!dedicated) xSemaphoreTake(busy, portMAX_DELAY);
			// direct call to STMICRO driver, blocking mode
			hspi->Instance->CR1 &= ~SPI_BAUDRATEPRESCALER_256;// reset to highest baudrate
			hspi->Instance->CR1 |= transmit_divisor;

			if (RESET.port != nullptr) RESET.set();				// make sure reset if high
			if (USE_CS) RESET_CS();								// CS low if needed
			/*
				HAL_OK       = 0x00,
				HAL_ERROR    = 0x01,
				HAL_BUSY     = 0x02,
				HAL_TIMEOUT  = 0x03
 	 	 	 */


			if ((cmdptr != nullptr) && (cmd_count != 0))
			{
				// command pointer says to send data with A0 down
				if (A0.port != nullptr) A0.reset();
				result = HAL_SPI_Transmit(hspi, cmdptr, cmd_count, timeout);
				// place to add delay if available
			}


			if ((dataptr != nullptr) && (data_count != 0))
			{
				// command pointer says to send data with A0 down
				if (A0.port != nullptr) A0.set();
				result = HAL_SPI_Transmit(hspi, dataptr, data_count, timeout);
				// place to add delay if available
//				while (hspi->State == HAL_SPI_STATE_BUSY_TX)
//				{
//					HAL_Delay(1);
//				}
			}
			if (USE_CS) SET_CS();								// CS high if needed
			// error reporting
			ERROR_CODE = hspi->ErrorCode;
			ERROR_REASON = (enum COMM_ERROR_TYPE) ERROR_CODE;
			operations++;
			// record errors if needed
			switch (result)
			{
				case HAL_ERROR:    					//= 0x01U,
				{
					fail++;
					break;
				}
				case HAL_BUSY:     					//= 0x02U,
				{
					fail++;
					break;
				}
				case HAL_TIMEOUT:  					//= 0x03U
				{
					fail++;
					break;
				}
				case HAL_OK:
				{
					// was OK
					succeed++;
					break;
				}
			}

			// return semaphore for next operation
			if (!dedicated) xSemaphoreGive(busy);
			time_stop = _MICROSECOND_TIMER.Instance->CNT;
			delta_time = time_stop - time_start;
			break;
		}
		

 

Using optimization for debug, this code works perfectly. 

Using G0 (no optimization), the code fails either at line #70 after executing line #61 (write two bytes), or the second call to the routine at line #61 (writing one byte per call).

This is a display driver routine.  Using version 1.19.0

The rest of the code in this routine simply returns HAL_OK.

 

0 REPLIES 0