soft timery w stylu ESP :)

Język C dla mikrokontrolerów ARM
ODPOWIEDZ
Awatar użytkownika
squeez
Użytkownik
Posty: 79
Rejestracja: 16 paź 2017, 23:52

soft timery w stylu ESP :)

Post autor: squeez » 04 lut 2018, 21:24

spodobały mi się timery softwerowe jakie są w SDK do ESP na tyle że postanowiłem przenieść je do STM32 :) w sumie można to przenieść na każdy inne uc ale z ARM o tyle fajnie że jest sobie SysTick który i tak biega, więc nie trzeba żadnego dodatkowego timera angażować.

plik nagłówkowy system.h

Kod: Zaznacz cały

typedef void os_TimerFunc(void *timer_arg);

typedef struct _os_TIMER_ {
    struct _os_TIMER_    *timer_next;
    uint32_t              timer_expire;
    uint32_t              timer_period;
    os_TimerFunc         *timer_func;
    void                 *timer_arg;
} os_Timer;

void os_timer_init(os_TimerFunc *func, void *arg);
void os_timer_setfn(os_Timer *timer, os_TimerFunc *func, void *arg);
void os_timer_arm(os_Timer *timer, uint32_t time, uint8_t repeat);
void os_timer_disarm(os_Timer *timer);
void os_timer_callback(void);
void os_timer_event(void);
Struktura żywcem ściągnięta z ESP :) ale że kodu nie ma otwartego tylko jest w bibliotece os_api to resztę dopisałem sam nieco po swojemu :)

Plik system.c

Kod: Zaznacz cały

#include "main.h"
#include "system.h"

os_Timer sys_timer;


void os_timer_init(os_TimerFunc *func, void *arg) {
	sys_timer.timer_next = 0;
	sys_timer.timer_expire = 1000;
	sys_timer.timer_period = 1000;
	if( func ) {
		sys_timer.timer_func = func;
	} else {
		sys_timer.timer_func = 0;
	}
	sys_timer.timer_arg = arg;
}


void os_timer_setfn(os_Timer *timer, os_TimerFunc *func, void *arg) {
	timer->timer_func = func;
	timer->timer_arg = arg;
}


void os_timer_arm(os_Timer *timer, uint32_t time, uint8_t repeat) {

	os_Timer *cur = &sys_timer;

	while( cur->timer_next ) {
		cur = cur->timer_next;
	}

	cur->timer_next = timer;

	timer->timer_expire = time;

	if( repeat ) {
		timer->timer_period = time;
	} else {
		timer->timer_period = 0;
	}
}


void os_timer_disarm(os_Timer *timer) {
	timer->timer_expire = 0;
	timer->timer_arg = 0;
	timer->timer_func = 0;
	timer->timer_period = 0;
}


void os_timer_callback(void) {
	os_Timer *cur = &sys_timer;
	os_Timer *next;

	do {
		cur->timer_expire--;
		next = cur->timer_next;
		cur = cur->timer_next;
	} while (  next );
}


void os_timer_event(void) {
	os_Timer *cur = &sys_timer;
	os_Timer *next;

	do {
		if( !cur->timer_expire ) {
			if( cur->timer_func ) {
				cur->timer_func( cur->timer_arg );

				if( cur->timer_period ) {
					cur->timer_expire = cur->timer_period;
				} else {
					cur->timer_func = 0;
				}
			}
		}
		next = cur->timer_next;
		cur = cur->timer_next;
	} while (  next );
}
a teraz użycie.

Kod: Zaznacz cały

#include "main.h"
#include "uart.h"
#include "system.h"

os_Timer mytimer;

void mytimerfunc(void *arg) {
	LL_GPIO_TogglePin(LED2_GPIO_PORT, LED2_PIN);
}

void sysfunc(void *arg) {
	uart_puts( arg );
}

int main(void) {

	SystemClock_Config();
	GPIO_conf();
	UART_conf();

	os_timer_init( sysfunc, "To ja STM32 :)\n");
	os_timer_setfn(&mytimer, mytimerfunc, 0);
	os_timer_arm(&mytimer, 100, 1);

	uart_puts("Hello World\n");

	while (1) {
		os_timer_event();
	}
}
Różnica jest taka że jest sobie taki jak by systemowy timer cykający do 1s (można to zmienić) i nicujemy funkcją os_timer_init( sysfunc, "To ja STM32 :)\n"); gdzie podajemy funkcję jak ma się wykonywać oraz wskaźnik na argument.

potem można sobie inicjować swoje timery i funkcje jakie mają być wykonane w tym przypadku co 1s po uarcie leci "To ja STM32 :)" a dioda LED na nucleo miga sobie co 100 mili sekund.

Ach no jeszcze trzeba calbacka podpiąć do handlera przerwania od Systicka i włączyć dla niego przerwania jak doliczy.

w moim przypadku:

Kod: Zaznacz cały

void SysTick_Handler(void) {
	os_timer_callback();
}
a przerwania dla systicka można albo na rejestrach ustawić bit TICKINT w rejestrze STK_CTRL. Ja piszę w oparciu o LL więc zmiany dokonałem w funkcji LL_InitTick() (dopisana jedna linijka - SysTick_CTRL_TICKINT_Msk)

Kod: Zaznacz cały

__STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks)
{
  /* Configure the SysTick to have interrupt in 1ms time base */
  SysTick->LOAD  = (uint32_t)((HCLKFrequency / Ticks) - 1UL);  /* set reload register */
  SysTick->VAL   = 0UL;                                       /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_ENABLE_Msk |                   /* Enable the Systick Timer */
				   SysTick_CTRL_TICKINT_Msk;				/* Enable Systick interrupt */
}
Wiem wiem kod banalny i każdy go sobie może napisać sam i pewnie lepiej, mi się spodobało podejście jakie jest w ESP.
Jeszcze uwaga ja systicka konfiguruje na 1ms ale jak wiadomo każdy może sobie to przerobić jak tam chce tykać.

Aha ... i zrobiłem tak że w pętli głównej jest event od odpalania calbacków timerów, dlatego żeby nie blokować przerwań.

PS. napisałem to dosłownie przed chwilą więc pewnie coś tam jeszcze zoptymalizuję ale działa :)

Awatar użytkownika
SunRiver
Administrator
Posty: 416
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: soft timery w stylu ESP :)

Post autor: SunRiver » 04 lut 2018, 21:41

Myślałęm że tylko ja mam chore pomysły :) Bardzo ładnie , widzę że mój kod trochę bardziej pomotany :)
.... z każdym bitem serca ....
💫SunDUINO
💦Google+
💦Kanał Youtube
💦Sotton

Awatar użytkownika
squeez
Użytkownik
Posty: 79
Rejestracja: 16 paź 2017, 23:52

Re: soft timery w stylu ESP :)

Post autor: squeez » 05 lut 2018, 10:38

Pola struktury można oczywiście dostosować do swoich potrzeb, jak ktoś nie potrzebuje 32 bitowej wartości to może zmienić na uint16_t i zaoszczędzić 4 bajty na ram.

Umieszczam kod choć nic wyszukanego nie jest z dwóch powodów.
1) napełniania forum treścią dobrze wpłynie na promowanie forum w wyszukiwarkach.
2) myślę że dobrze dzielić się nawet jak to nic wielkiego ale innym czasami może się przydać :) dlatego zachęcam innych do podobnych działań :)

Takie prawdziwe dzielenie się (bezinteresowne) a nie sprzedawanie wiedzy pod egidą "dzielenia" :P

Awatar użytkownika
SunRiver
Administrator
Posty: 416
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: soft timery w stylu ESP :)

Post autor: SunRiver » 05 lut 2018, 12:51

i tej wersji się trzymajmy :)
.... z każdym bitem serca ....
💫SunDUINO
💦Google+
💦Kanał Youtube
💦Sotton

jarecki
Użytkownik
Posty: 10
Rejestracja: 25 paź 2017, 11:20

Re: soft timery w stylu ESP :)

Post autor: jarecki » 08 lut 2018, 15:08

squeez pisze:
04 lut 2018, 21:24
Wiem wiem kod banalny i każdy go sobie może napisać sam i pewnie lepiej
Bardzo fajnie to wygląda, dzięki że się podzieliłeś :) Dużo można się nauczyć analizując takie kody :) przynajmniej w moim przypadku :)

ODPOWIEDZ