LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

[STM32] Wyjątki C++ na przykładzie systemu ISIX-RTOS

Tab. 1. Błędy logiczne sygnalizowane wyjątkami

Klasa wyjątku Opis
logic_error Klasa bazowa dla pozostałych błędów logicznych wywodząca się z exception.
domain_error Liczba poza dziedziną.
invalid_argument Błędny argument przekazany do funkcji.
length_error Błąd rozmiaru. Np przy próbie zmiany rozmiaru wektora.
out_of range Wartość poza zakresem.

 

Tab. 2. Błędy wykonania sygnalizowane wyjątkami

Klasa wyjątku Opis
runtime_error Klasa bazowa dla pozostałych błędów wykonania wywodząca się z exception.
range_error Błąd zakresu.
overflow_error Błąd przepełnienia.
underflow_error Błąd niedomiaru.

 

Oczywiście każdy z tych wyjątków może być zgłaszany nie tylko przez bibliotekę standardową, ale także przez kod użytkownika. Bazując na powyższych klasach, hierarchia wyjątków może być rozbudowywana w razie potrzeb przez użytkownika.

Przykład praktyczny: obsługa wyjątków w ISIX-RTOS

Po zapoznaniu się z podstawowymi wiadomościami teoretycznymi na temat wyjątków w C++ , pokażemy, że mogą być stosowane z powodzeniem również w przypadku nieco większych mikrokontrolerów. Pozwalając na znaczące podniesienie niezawodności działania programu, oraz przy stosowaniu z umiarem zapewniają również podniesienie ogólnej wydajności aplikacji.

Posłużmy się teraz prostym przykładem (platforma STM32Butterfly), w którym jeden wątek będzie odpowiedzialny za mruganie diodą D1, i sygnalizował będzie jedynie prawidłowe działanie systemu operacyjnego. Natomiast drugi wątek, będzie zmieniał stan diody D2 na przeciwny w przypadku wciśnięcia klawisza joysticka OK. W przypadku wciśnięcia klawisza DOWN, lub UP, zgłaszany będzie wyjątek, który będzie symulował wystąpienie, błędu. Dodatkowo na linii PE0 wystawiany będzie stan 1 przez czas od momentu zgłoszenia wyjątku, do jego przechwycenia co pozwoli na zbadanie ogólnej wydajności obsługi wyjątków w GCC na architekturze CORTEX-M3. Kod programu przedstawiono na poniższym listingu:

namespace app
{

class ledblink: public isix::task_base
{
public:
	//Constructor
	ledblink() : task_base(STACK_SIZE,TASK_PRIO), LED_PORT(GPIOE)
	{
		using namespace stm32;
		//Enable PE in APB2
		RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
		io_config(LED_PORT,LED_PIN,GPIO_MODE_10MHZ,GPIO_CNF_GPIO_PP);
	}
protected:
	//Main function
	virtual void main()
	{
		while(true)
		{
			//Enable LED
			stm32::io_clr( LED_PORT, LED_PIN );
			//Wait time
			isix::isix_wait( isix::isix_ms2tick(BLINK_TIME) );
			//Disable LED
			stm32::io_set( LED_PORT, LED_PIN );
			//Wait time
			isix::isix_wait( isix::isix_ms2tick(BLINK_TIME) );
		}
	}
private:
	static const unsigned STACK_SIZE = 256;
	static const unsigned TASK_PRIO = 3;
	GPIO_TypeDef * const LED_PORT;
	static const unsigned LED_PIN = 14;
	static const unsigned BLINK_TIME = 500;
};
/* ------------------------------------------------------------------ */

class ledkey: public isix::task_base
{
public:
	//Constructor
	ledkey()
		: task_base(STACK_SIZE,TASK_PRIO), is_enabled(false),
		 KEY_PORT(GPIOE), LED_PORT(GPIOE)
	{
		using namespace stm32;
		//Enable PE in APB2
		RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
		io_config(LED_PORT,LED_PIN,GPIO_MODE_10MHZ,GPIO_CNF_GPIO_PP);
		io_config(LED_PORT,NOTIFY_PIN,GPIO_MODE_10MHZ,GPIO_CNF_GPIO_PP);
	}
protected:
	//Main function
	virtual void main()
	{
		//Last key state
		bool state = true;
		//Task/thread main loop
		try
		{
			while(true)
			{
				execute_keycheck(state);
			}
		}
		catch( int &val)
		{
			stm32::io_clr( LED_PORT,NOTIFY_PIN );
			dbprintf("INT exception [%d]", val);
		}
		catch( const std::exception &e )
		{
			stm32::io_clr( LED_PORT,NOTIFY_PIN );
			dbprintf("std::exception [%s]", e.what());
		}
	}
private:
	//Execute keycheck function
	void execute_keycheck(bool &p_state)
	{

		//Change state on rising edge
		if(stm32::io_get(KEY_PORT, KEY_PIN) && !p_state)
		{
			is_enabled = !is_enabled;
		}
		//Get previous state
		p_state = stm32::io_get(KEY_PORT, KEY_PIN);
		//If enabled change state
		if(is_enabled) stm32::io_clr( LED_PORT, LED_PIN );
		else stm32::io_set( LED_PORT, LED_PIN );
		//Wait short time
		isix::isix_wait( isix::isix_ms2tick(DELAY_TIME) );
		if( !stm32::io_get(KEY_PORT, KEY_RAISE_LOGIC ))
		{
			/** From raise to catch 151us **/
			stm32::io_set( LED_PORT,NOTIFY_PIN );
			throw(std::logic_error("critical error raised"));
		}
		if( !stm32::io_get(KEY_PORT, KEY_RAISE_INT ))
		{
			/** From raise to catch 108us **/
			stm32::io_set( LED_PORT,NOTIFY_PIN );
			throw(-1);
		}
	}
private:
		static const unsigned STACK_SIZE = 2048;
		static const unsigned TASK_PRIO = 3;
		bool is_enabled;
		GPIO_TypeDef * const KEY_PORT;
		GPIO_TypeDef * const LED_PORT;
		static const unsigned LED_PIN = 15;
		static const unsigned KEY_PIN = 8;
		static const unsigned NOTIFY_PIN = 0;
		static const unsigned KEY_RAISE_LOGIC = 9;
		static const unsigned KEY_RAISE_INT = 10;
		static const unsigned DELAY_TIME = 25;
};


}
/* ------------------------------------------------------------------ */
//App main entry point
int main()
{
	 dblog_init( stm32::usartsimple_putc, NULL, stm32::usartsimple_init,
	  		USART2,115200,true, config::PCLK1_HZ, config::PCLK2_HZ );
	 dbprintf(" Exceptions presentation app using ISIXRTOS ");


	//The blinker class
	static app::ledblink led_blinker;
	//The ledkey class
	static app::ledkey led_key;
	//Start the isix scheduler
	isix::isix_start_scheduler();
}