cancel
Showing results for 
Search instead for 
Did you mean: 

How should I build an effective peripheral "driver" ?

magene
Senior II

I've spent a fair amount of time getting small bits of code working so I can build them up into a larger working application. The code below works but I'm struggling with a way to move the parts related to GPS and the UART into separate files or classes or whatever will be effective so that I can call the GPS functions like getTime and getPosition from elsewhere in my program. Right now GPS1 is a class that uses uart4 to talk to a uBlox GPS receiver. My main app is a pretty straightforward non-blocking state machine. every state is a class and all the states are kept in stateArray.

In the code below I can see the HAL callbacks and my processGPS_RXComplete() get called and everything works fine. When I move moveToInitPlatformStateActions() into the InitPlatformState, only the UART4_IRQHandler() gets called. I've tried moving the HAL stuff and my processGPS_RXComplete() into the InitPlatformState class and/or the GPS class without success so far.

I'm pretty sure at least part of the problem is I don't know how to make the various HAL subroutines visible to my classes and am probably using extern "C" and extern incorrectly. And probably worse is instantiating classes as static in moveToInitPlatformStateActions() but ti's the only way I've been able to make it work.

I know this is a pretty complicated question and I will greatly appreciate any help. And it might be that trying to do this with classes is just too complicated given my current state of knowledge.

Thanks

int main(void)
{
	bool doEntryActions = true;
	bool runMission = true;
	
	initStateArray();
	MPU_Config();
	HAL_Init();
	SystemClock_Config();
	BSP_LED_Init(LED_OK);
	BSP_LED_Init(LED_ERROR);
	BSP_SD_Init(0);
	BSP_SD_DetectITConfig(0);
	MX_GPIO_Init();
	
	currentState = initPlatform;
	doEntryActions = true;
	while (runMission)
	{
		if (doEntryActions)
		{
			stateArray[currentState]->doStateEntry();
			doEntryActions = false;
		}
		
		stateArray[currentState]->doStateActions();
 
		moveToInitPlatformStateActions();
		
		nextState = stateArray[currentState]->checkEvents();
		
		if (nextState != currentState)
		{
			stateArray[currentState]->doStateExit(false);
			currentState = nextState;
			//currentStateLabel = stateArray[SV.currentState]->stateID;
			doEntryActions = true;
		}
		HAL_Delay(1);
	}	
}
 
void moveToInitPlatformStateActions()
{
	static GPS1 gps1 = GPS1::getInstance();
	static mcuRealTimeClock mcuRTC = mcuRealTimeClock::getInstance();
	static Logger logger = Logger::getInstance(); mcuRTC.getTimestamp();
 
	gpsMsgReceived = false;
	gps1.getTime();
	while (gpsFIFO.isEmpty())
	{
		HAL_Delay(1);
	}
 
	mcuRealTimeClock::DateTimeStruct gpsDateTime;
	gpsDateTime = gps1.parseTime();	
	mcuRTC.setTime(gpsDateTime);
	mcuRTC.getTimestamp();
 
	if (logger.openFiles() != FR_OK)
	{
		//TODO print error message and probably exit
	}
}
 
extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uartHandle)
{
	if (uartHandle->Instance == UART4)
	{	
		processGPS_RXComplete(uartHandle);			
	}
}
 
extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef *uartHandle)
{
	cout << "Got to HAL_UART_TxCpltCallback() " << endl;
}
 
extern void processGPS_RXComplete(UART_HandleTypeDef *uartHandle)  //TODO Make this part of GPS1 class
{
	if (rxBuffer[0] != 0)
	{
		gpsMessage[gpsMsgCount] = rxBuffer[0];
		gpsMsgCount++;
		if (rxBuffer[0] == '\n')
		{   
			gpsFIFO.enqueue(sysTickCounter, gpsMessage);
			gpsMsgReceived = true;
			cout << "processGPSRXComplete got LF terminated msg: " << gpsMessage << endl;
		}
		else
			HAL_UART_Receive_IT(uartHandle, rxBuffer, 1);
	}
	else
	{
		HAL_UART_Receive_IT(uartHandle, rxBuffer, 1);
	}
 
}
extern "C" void UART4_IRQHandler()
{
	HAL_UART_IRQHandler(&uart4Handle); 		
}

1 REPLY 1
Pavel A.
Evangelist III

Looks like it is indeed worth to involve external help (contractor).