91 lines
3.0 KiB
C
91 lines
3.0 KiB
C
|
/***************************************************************************
|
||
|
* Copyright (C) 01/2008 by Olaf Rempel *
|
||
|
* razzor@kopf-tisch.de *
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; version 2 of the License *
|
||
|
* *
|
||
|
* This program is distributed in the hope that it will be useful, *
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||
|
* GNU General Public License for more details. *
|
||
|
* *
|
||
|
* You should have received a copy of the GNU General Public License *
|
||
|
* along with this program; if not, write to the *
|
||
|
* Free Software Foundation, Inc., *
|
||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
|
***************************************************************************/
|
||
|
#include "AT91SAM7S256.h"
|
||
|
#include "at91_pitc.h"
|
||
|
#include "at91_sysc.h"
|
||
|
#include "board.h"
|
||
|
#include "static_alloc.h"
|
||
|
|
||
|
/* PIV is 20bit -> min. 3Hz @48MHz MCK */
|
||
|
#define HZ_TO_PIV(HZ) (MCK / (16 * HZ))
|
||
|
|
||
|
static LIST_HEAD(timer_list);
|
||
|
volatile static uint32_t pitc_ticks;
|
||
|
|
||
|
struct pitc_timer * alloc_pitc_timer(uint32_t interval, uint32_t (*func)(struct pitc_timer *), void *privdata)
|
||
|
{
|
||
|
struct pitc_timer *timer = static_alloc(sizeof(struct pitc_timer));
|
||
|
timer->interval = interval;
|
||
|
timer->func = func;
|
||
|
timer->privdata = privdata;
|
||
|
|
||
|
return timer;
|
||
|
}
|
||
|
|
||
|
void pitc_schedule_timer(struct pitc_timer *timer)
|
||
|
{
|
||
|
timer->nextrun = timer->interval + pitc_ticks;
|
||
|
|
||
|
struct pitc_timer *search;
|
||
|
list_for_each_entry(search, &timer_list, list)
|
||
|
if (search->nextrun > timer->nextrun)
|
||
|
break;
|
||
|
|
||
|
list_add_tail(&timer->list, &search->list);
|
||
|
}
|
||
|
|
||
|
static void pitc_isr(uint32_t status)
|
||
|
{
|
||
|
/* get Ticks and clear interrupt */
|
||
|
pitc_ticks += (*AT91C_PITC_PIVR & AT91C_PITC_PICNT) >> 20;
|
||
|
|
||
|
struct pitc_timer *search, *tmp;
|
||
|
list_for_each_entry_safe(search, tmp, &timer_list, list) {
|
||
|
/* if this entry not scheduled yet, abort search */
|
||
|
if (pitc_ticks < search->nextrun)
|
||
|
break;
|
||
|
|
||
|
/* remove from list */
|
||
|
list_del(&search->list);
|
||
|
|
||
|
/* exec handler */
|
||
|
if (search->func(search) == PITC_REMOVE_TIMER) {
|
||
|
/* one-shot timer, mark as completed */
|
||
|
search->nextrun = 0x00;
|
||
|
continue;
|
||
|
}
|
||
|
/* interval timer, reschedule it */
|
||
|
pitc_schedule_timer(search);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint32_t pitc_get_ticks(void)
|
||
|
{
|
||
|
return pitc_ticks;
|
||
|
}
|
||
|
|
||
|
void at91_pitc_init(void)
|
||
|
{
|
||
|
sysc_register_isr(AT91_SYSIRQ_PIT, &pitc_isr);
|
||
|
|
||
|
*AT91C_PITC_PIMR = (AT91C_PITC_PIV & HZ_TO_PIV(100)) |
|
||
|
AT91C_PITC_PITEN |
|
||
|
AT91C_PITC_PITIEN;
|
||
|
}
|