Пример работы с protothreads на GCC-AVR

01.05.2011 22:10 / Артём Волк / 1340 просмотров / ...

Вдохновившись описанием Protothreads у BSVi, набросал небольшой пример их использования в виде программы, мигающей двумя светодиодами с разной частотой. Для пущей важности был использован system tick timer и супер-макросы для работы с GPIO.

Интересно, правильно ли я понял идею протопотоков? :)

Архив с исходниками можно скачать.

#include "libs/common.h"

#define	LED1	B, 5, H
#define	LED2	B, 4, H

// IO Init
static inline void init_io(void)
{
	// Turn UART off after bootloader
	UCSRB = 0;

	DRIVER(LED1, OUT);
	DRIVER(LED2, OUT);

	#if DEBUG_BUILD
		// UART
		uart_init(UART_BAUD_RATE);
		stdout = &uart_str;
		puts_P(PSTR("MCU started..."));
	#endif
}

static struct pt blink1_pt, blink2_pt;

static PT_THREAD(blink1(struct pt *pt))
{
	static uint32_t last_timer;

	PT_BEGIN(pt);

	last_timer = st_millis();
	ON(LED1);

	#if DEBUG_BUILD
		puts_P(PSTR("Blinking protothread #1 started..."));
	#endif


	while(1)
	{
		PT_WAIT_UNTIL(pt, (st_millis() - last_timer) >= 500);
		last_timer = st_millis();
		TOGGLE(LED1);
		#if DEBUG_BUILD
			printf_P(PSTR("Blink #1 at %" PRIu32 "\n"), last_timer);
		#endif
	}
	PT_END(pt);
}

static PT_THREAD(blink2(struct pt *pt))
{
	static uint32_t last_timer;

	PT_BEGIN(pt);

	last_timer = st_millis();
	ON(LED2);

	#if DEBUG_BUILD
		puts_P(PSTR("Blinking protothread #2 started..."));
	#endif

	while(1)
	{
		PT_WAIT_UNTIL(pt, (st_millis() - last_timer) >= 1000);
		last_timer = st_millis();
		TOGGLE(LED2);
		#if DEBUG_BUILD
			printf_P(PSTR("Blink #2 at %" PRIu32 "\n"), last_timer);
		#endif
	}
	PT_END(pt);
}


int main(void)
{
	init_io();
	st_init();

	sei();

	PT_INIT(&blink1_pt);
	PT_INIT(&blink2_pt);

	while(1)
	{
		blink1(&blink1_pt);
		blink2(&blink2_pt);
	}
}