Implement rtimers for ADuCRF101

This commit is contained in:
Jim Paris 2014-06-27 18:19:05 -04:00
parent c8716f4d57
commit ad141b00fb
5 changed files with 96 additions and 15 deletions

View file

@ -101,6 +101,7 @@ CONTIKI_CPU_DIRS += ../common/CMSIS
CONTIKI_CPU_DIRS += . CONTIKI_CPU_DIRS += .
CONTIKI_SOURCEFILES += slip-arch.c CONTIKI_SOURCEFILES += slip-arch.c
CONTIKI_SOURCEFILES += rtimer-arch.c
CONTIKI_CPU_DIRS += dev CONTIKI_CPU_DIRS += dev
CONTIKI_SOURCEFILES += uart.c CONTIKI_SOURCEFILES += uart.c

View file

@ -45,8 +45,8 @@
typedef uint32_t clock_time_t; typedef uint32_t clock_time_t;
typedef uint16_t uip_stats_t; typedef uint16_t uip_stats_t;
typedef unsigned long rtimer_clock_t; typedef uint32_t rtimer_clock_t;
#define RTIMER_CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) #define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0)
rtimer_clock_t rtimer_arch_now(void); rtimer_clock_t rtimer_arch_now(void);
#endif #endif

View file

@ -35,25 +35,104 @@
* \author Jim Paris <jim.paris@rigado.com> * \author Jim Paris <jim.paris@rigado.com>
*/ */
#include <contiki.h>
#include "rtimer-arch.h" #include "rtimer-arch.h"
#include "aducrf101-contiki.h"
/* rtimer on the ADuCRF101 is implemented with the "wakeup" timer.
(timer 2). It should be clocked from an external crystal,
but if that doesn't seem to be present, this code will select the
imprecise internal 32.768 KHz oscillator instead. */
static void
_timer2_enable(int enable)
{
T2CON_ENABLE_BBA = enable;
clock_time_t now = clock_time();
while(T2STA_CON_BBA) {
/* Synchronizing settings may fail if the chosen clock isn't running;
wait no more than 1ms for it */
if((clock_time() - now) > (CLOCK_SECOND / 1000)) {
break;
}
}
}
static uint32_t
_timer2_val(void)
{
/* This is atomic because the FREEZE bit is set in T2CON. */
uint32_t now;
now = pADI_WUT->T2VAL0;
now |= pADI_WUT->T2VAL1 << 16;
return now;
}
static uint32_t
_timer2_measure_freq(void)
{
const int test_usec = 10000;
uint32_t now = _timer2_val();
clock_delay_usec(test_usec);
return (_timer2_val() - now) * (1000000 / test_usec);
}
void void
rtimer_arch_init(void) rtimer_arch_init(void)
{ {
uint32_t freq;
const char *timer = "LFXTAL";
_timer2_enable(0);
pADI_WUT->T2CON = T2CON_PRE_DIV1 | T2CON_MOD_FREERUN | T2CON_FREEZE_EN |
T2CON_WUEN_EN;
/* Try 32.768 KHz crystal */
pADI_WUT->T2CON |= T2CON_CLK_LFXTAL;
_timer2_enable(1);
freq = _timer2_measure_freq();
if(freq < 20000 || freq > 40000) {
/* No good; use 32.768 KHz internal oscillator */
_timer2_enable(0);
pADI_WUT->T2CON &= ~T2CON_CLK_MSK;
pADI_WUT->T2CON |= T2CON_CLK_LFOSC;
_timer2_enable(1);
freq = _timer2_measure_freq();
timer = "LFOSC";
} }
/*---------------------------------------------------------------------------*/
void printf("Using %s for rtimer (%ld Hz)\n", timer, freq);
rtimer_arch_schedule(rtimer_clock_t t)
{ /* Enable interrupt in NVIC, but disable in WUT for now. */
pADI_WUT->T2IEN = 0;
NVIC_EnableIRQ(WUT_IRQn);
} }
/*---------------------------------------------------------------------------*/
void
rtimer_arch_set(rtimer_clock_t t)
{
}
/*---------------------------------------------------------------------------*/
rtimer_clock_t rtimer_clock_t
rtimer_arch_now(void) rtimer_arch_now(void)
{ {
return 0; /* This is atomic because the FREEZE bit is set in T2CON. */
return _timer2_val();
}
void
rtimer_arch_schedule(rtimer_clock_t t)
{
uint32_t now = _timer2_val();
/* Minimum of 5 wakeup timer ticks */
if((int32_t)(t - now) < 5) {
t = now + 5;
}
/* Set T2WUFB to match at target time */
T2IEN_WUFB_BBA = 0;
pADI_WUT->T2WUFB0 = (t & 0xffff);
pADI_WUT->T2WUFB1 = (t >> 16);
T2IEN_WUFB_BBA = 1;
}
void
WakeUp_Int_Handler(void)
{
/* clear interrupt */
T2CLRI_WUFB_BBA = 1;
/* disable T2WUFB match */
T2IEN_WUFB_BBA = 0;
rtimer_run_next();
} }

View file

@ -40,7 +40,7 @@
#include <stdint.h> #include <stdint.h>
#define RTIMER_ARCH_SECOND (1000) #define RTIMER_ARCH_SECOND (32768)
#include "sys/rtimer.h" #include "sys/rtimer.h"

View file

@ -132,6 +132,7 @@ main(int argc, char **argv)
process_init(); process_init();
process_start(&etimer_process, NULL); process_start(&etimer_process, NULL);
ctimer_init(); ctimer_init();
rtimer_init();
set_rime_addr(); set_rime_addr();