Implement rtimers for ADuCRF101
This commit is contained in:
parent
c8716f4d57
commit
ad141b00fb
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue