[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();
}

Technologie End of Life i bezpieczeństwo sieci – wyzwania Europy związane z tzw. długiem technologicznym
Najczęstsze błędy firm przy wyborze dostawcy energii i jak ich uniknąć
Fotorezystor, czyli czujnik światła dwojakiego działania. Przykład innowacji w automatyce i elektronice możliwej dzięki technologii fotooporników 



