cancel
Showing results for 
Search instead for 
Did you mean: 

Non-blocking SDIO SD Access - SDIO Timeout

bluscape
Associate III

I've been working on making my SD SDIO card access non blocking. My implementation is a derivative from the standard ST SDIO SD driver (stm324xg_eval_sdio_sd).

I'm using Protothreads (basically a state machine) to make the SD SDIO calls non-blocking and allow the program execution to continue while I'm waiting for the operations to complete. For some unknown reason, and I've not been able to identify the cause, when I continue with the program execution, I get a timeout error from the SDIO interface. But when I block and wait for the result all is fine. This is what I currently have:

static PT_THREAD(sd_CMDResponse1Error_V(struct pt* Thread_PS, uint8_t CMD_U8, SD_Error* SDResult_PE))
{
	static uint32_t Status_U32;
	uint32_t Response_U32;
	static uint32_t Timeout_U32;
 
	// Begin the thread
	PT_BEGIN(Thread_PS);
 
	// Initialise the result
	*SDResult_PE = SD_OK;
 
	// Initialise the timeout
	Timeout_U32 = SDIO_CMD0TIMEOUT;
 
	while (1)
	{
		// Get the status
		Status_U32 = SDIO->STA;
 
		// If we received the status or timeout
		if ((Status_U32 & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))||(Timeout_U32 == 0))
		{
			break;
		}
 
		// Decrease the timeout
		Timeout_U32--;
 
		// Yield the thread
		PT_YIELD(Thread_PS);
	}
 
	// If there was a timeout
	if (Status_U32 & SDIO_FLAG_CTIMEOUT)
	{
		// Set the result
		*SDResult_PE = SD_CMD_RSP_TIMEOUT;
 
		// Clear the flags
		SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
 
		// Exit the thread
		PT_EXIT(Thread_PS);
	}
	else
	// If the CRC failed
	if (Status_U32 & SDIO_FLAG_CCRCFAIL)
	{
		// Set the result
		*SDResult_PE = SD_CMD_CRC_FAIL;
 
		// Clear the flags
		SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
 
		// Exit the thread
		PT_EXIT(Thread_PS);
	}
 
	.....
 
	// End the thread
	PT_END(Thread_PS);
}

When I cal PT_YIELD to allow the program execution to continu, I get a timeout error. But when I remove the PT_YIELD statement, the IO completes without any errors.

It does not make sense. Because whether I exit and return to check the SDIO status (SDIO->STA) or sit and wait for the SDIO status (SDIO->STA) it should not make any difference.

Nothing else is accessing the SDIO when I do exit and return.

Maybe someone else can shed some light on this?

Addendum

For those who are not familiar with Protothreads, I've quickly re-written this function with a basic state machine (sort of what the Protothreads implementation would have looked liked when expanded).

static char sd_CMDResponse1Error_C(int State_S, uint8_t CMD_U8, SD_Error* SDResult_PE)
{
	static uint32_t Status_U32;
	uint32_t Response_U32;
	static uint32_t Timeout_U32;
 
	switch (State_S)
	{
		case 0:
 
			// Initialise the result
			*SDResult_PE = SD_OK;
 
			// Initialise the timeout
			Timeout_U32 = SDIO_CMD0TIMEOUT;
 
			// Go to the next state
			State_S = 1;
 
			// Fall through to next state
 
		case 1:
 
			// Get the status
			Status_U32 = SDIO->STA;
 
			// If we received the status or timeout
			if ((Status_U32 & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))||(Timeout_U32 == 0))
			{
				// Go to the next state
				State_S = 2;
 
				// Fall through to the next state
			}
			else
			{
				// Decrease the timeout
				Timeout_U32--;
 
				return PT_YIELDED;
			}
 
		case 2:
 
			// If there was a timeout
			if (Status_U32 & SDIO_FLAG_CTIMEOUT)
			{
				// Set the SD result
				*SDResult_PE = SD_CMD_RSP_TIMEOUT;
 
				// Clear the flags
				SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
 
				return PT_EXITED;
			}
			else
			// If the CRC failed
			if (Status_U32 & SDIO_FLAG_CCRCFAIL)
			{
				// Set the SD result
				*SDResult_PE = SD_CMD_CRC_FAIL;
 
				// Clear the flags
				SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
 
				return PT_EXITED;
			}
 
			....
 
			// Fall through to PT_ENDED (No default needed)
	}
 
	return PT_ENDED;
}

1 ACCEPTED SOLUTION

Accepted Solutions
bluscape
Associate III

Ok, found the issue. There was another disk access when the thread yielded.

View solution in original post

1 REPLY 1
bluscape
Associate III

Ok, found the issue. There was another disk access when the thread yielded.