#include <string.h>
#define ALARM_TIMER_PERIPH_HANDLE BSP430_TIMER_CCACLK_PERIPH_HANDLE
#if (APP_SOURCE_SMCLK - 0)
#define APP_TASSEL TASSEL_2
#else
#define APP_TASSEL TASSEL_1
#endif
unsigned long alarm_Hz;
#define MAX_TIMERS 7
unsigned int nTimers;
unsigned long wakeups;
enum {
FLG_SkipLost = 0x01,
FLG_WakeFromLPM = 0x02,
};
typedef struct sAlarmStats {
int flags;
unsigned long count;
int rc;
unsigned long interval_tck;
unsigned long sum_late;
unsigned long last_late;
unsigned long max_late;
unsigned long lost;
} sAlarmStats;
volatile sAlarmStats alarm_stats[MAX_TIMERS];
static int
{
volatile sAlarmStats * ap;
ap = alarm_stats + alarm->
ccidx;
ap->count += 1;
if (ap->last_late > ap->max_late) {
ap->max_late = ap->last_late;
}
ap->sum_late += ap->last_late;
if (0 < ap->interval_tck) {
unsigned long setting_tck = alarm->
setting_tck + ap->interval_tck;
unsigned int lost = 0;
if (setting_tck <= now_tck) {
lost = (now_tck - setting_tck + ap->interval_tck - 1) / ap->interval_tck;
setting_tck += lost * ap->interval_tck;
}
while ((0 != ap->rc) && (ap->flags & FLG_SkipLost) && (1000 > lost)) {
++lost;
setting_tck += ap->interval_tck;
}
ap->lost += lost;
} else {
}
}
#define LAST_COMMAND NULL
static int
cmd_synctest (const char * command)
{
const unsigned long interval =
#if (APP_SOURCE_SMCLK - 0)
100000UL
#else
10000UL
#endif
;
int cc;
do {
alarmHAL_->
hpl->
ctl &= ~(MC0 | MC1);
for (cc = 0; cc < nTimers; ++cc) {
if (NULL != ap) {
alarm_stats[cc].interval_tck = interval;
alarm_stats[cc].flags |= FLG_SkipLost;
}
}
} while (0);
return 0;
}
.help = "# synctest alarm cc",
.next = LAST_COMMAND,
.param.simple_handler = cmd_synctest
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_synctest)
static int
cmd_autotest (const char * command)
{
static const unsigned long base[] = {
#if 0
17, 31, 61, 127, 256, 509, 1021
#endif
#if 0
11, 101, 499, 997, 499, 10007, 19997
#endif
#if 1
16381, 32749, 32771, 65537, 131101, 262147, 524309
#endif
};
size_t nbase = sizeof(base)/sizeof(*base);
int cc;
do {
size_t bi = 0;
for (cc = 0; cc < nTimers; ++cc) {
if (NULL != ap) {
cprintf(
"config %p %u with %lu\n", ap, cc, base[bi]);
if (bi < nbase) {
alarm_stats[cc].interval_tck = base[bi];
++bi;
} else {
}
}
}
} while (0);
return 0;
}
.help = "# autotest alarm cc",
.next = LAST_COMMAND,
.param.simple_handler = cmd_autotest
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_autotest)
static int
cmd_cancel (const char * command)
{
int rv;
unsigned int cc;
const char * argstr = command;
size_t argstr_len = strlen(argstr);
argstr_len = strlen(argstr);
if ((0 == rv) && (0 <= cc) && (cc < nTimers)) {
do {
} while (0);
cprintf(
"Cancel %u produced %d\n", cc, rv);
} else {
cprintf(
"Bad input: %s\n", command);
}
return rv;
}
.help = "{cc} # cancel alarm cc",
.next = LAST_COMMAND,
.param.simple_handler = cmd_cancel
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_cancel)
static int
cmd_alarm (const char * command)
{
int rv;
unsigned int cc;
long rel_when;
const char * argstr = command;
size_t argstr_len = strlen(argstr);
argstr_len = strlen(argstr);
if (0 == rv) {
}
if (0 == rv) {
if ((0 <= cc) && (cc < nTimers)) {
unsigned long abs_when;
do {
} while (0);
cprintf(
"Set %u in %ld (%lu) produced %d\n",
cc, rel_when, abs_when, rv);
} else {
cprintf(
"Invalid cc value %u\n", cc);
}
} else {
cprintf(
"Bad input: %s\n", command);
}
return rv;
}
.help = "{cc} {rel_when} # set alarm for rel_when ticks",
.next = LAST_COMMAND,
.param.simple_handler = cmd_alarm
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_alarm)
static int
cmd_flags (const char * command)
{
int rv;
unsigned int cc;
const char * key;
int enablep = 0;
const char * argstr = command;
size_t argstr_len = strlen(argstr);
int flags = 0;
argstr_len = strlen(argstr);
key = argstr;
if ((0 > cc) || (nTimers <= cc)) {
rv = -1;
}
while (0 == rv) {
unsigned int flag;
size_t key_len;
if (0 == key_len) {
break;
}
enablep = -1;
if ('+' == *key) {
enablep = 1;
} else if ('-' == *key) {
enablep = 0;
} else {
rv = -1;
}
++key;
--key_len;
if (0 == strncmp("wake", key, key_len)) {
flag = FLG_WakeFromLPM;
} else if (0 == strncmp("skip", key, key_len)) {
flag = FLG_SkipLost;
} else {
rv = -1;
}
if (0 == rv) {
flags |= flag;
if (enablep) {
alarm_stats[cc].flags |= flag;
} else {
alarm_stats[cc].flags &= ~flag;
}
}
}
cprintf(
"Successfully modified flags 0x%x\n", flags);
if (0 != rv) {
}
return rv;
}
.help = "{cc} {[+-]flg}... # enable/disable wake skip",
.next = LAST_COMMAND,
.param.simple_handler = cmd_flags
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_flags)
static int
cmd_interval (const char * command)
{
int rv;
unsigned int cc;
unsigned long interval;
const char * argstr = command;
size_t argstr_len = strlen(argstr);
argstr_len = strlen(argstr);
if (0 == rv) {
}
if (0 == rv) {
if ((0 <= cc) && (cc < nTimers)) {
alarm_stats[cc].interval_tck = interval;
} else {
cprintf(
"Invalid cc value %u\n", cc);
}
} else {
cprintf(
"Bad input: %s\n", command);
}
return rv;
}
.help = "{cc} {interval} # set alarm interval, 0 one-shot",
.next = LAST_COMMAND,
.param.simple_handler = cmd_interval
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_interval)
static int
cmd_configure_ (const char * command,
int enablep)
{
int rv;
unsigned int cc;
const char * input;
const char * argstr = command;
size_t argstr_len = strlen(argstr);
argstr_len = strlen(argstr);
do {
input = argstr;
if ((0 == rv) && (0 <= cc) && (cc < nTimers)) {
if (enablep) {
} else {
}
if (0 != rv) {
cprintf(
"Failed cc index %d: %d\n", cc, rv);
return rv;
}
} else {
rv = -1;
}
} while (0 == rv);
if (0 < argstr_len) {
cprintf(
"Invalid cc index at '%s'\n", input);
return -1;
}
return 0;
}
static int
cmd_disable (const char * command)
{
return cmd_configure_(command, 0);
}
.help = "{cc}... # disable alarm cc",
.next = LAST_COMMAND,
.param.simple_handler = cmd_disable
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_disable)
static int
cmd_enable (const char * command)
{
return cmd_configure_(command, 1);
}
.help = "{cc}... # enable alarm cc",
.next = LAST_COMMAND,
.param.simple_handler = cmd_enable
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_enable)
static int
cmd_reset (const char * command)
{
int rv;
unsigned int cc;
const char * argstr = command;
size_t argstr_len = strlen(argstr);
do {
if ((0 == rv) && (0 <= cc) && (cc < nTimers)) {
volatile sAlarmStats * sp = alarm_stats + cc;
do {
sp->count = 0;
sp->last_late = 0;
sp->max_late = 0;
sp->sum_late = 0;
sp->lost = 0;
} while (0);
}
} while (0 == rv);
return 0;
}
.help = "{cc}... # reset alarm statistics",
.next = LAST_COMMAND,
.param.simple_handler = cmd_reset
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_reset)
static int
cmd_stats (const char * command)
{
int ai;
for (ai = 0; ai < nTimers; ++ai) {
volatile sAlarmStats * sp = alarm_stats + ai;
if (NULL == alarm[ai]) {
cprintf(
" %u: not available\n", ai);
} else {
cprintf(
" %u: %cset %cenab %cwake %cskip cnt %9lu, rc %d, inter %6lu\n"
" lost %6lu; late: last %6ld, max %6lu, ave %6lu\n",
ai,
(sp->flags & FLG_WakeFromLPM) ? '+' : '-',
(sp->flags & FLG_SkipLost) ? '+' : '-',
sp->count, sp->rc, sp->interval_tck,
sp->lost, sp->last_late, sp->max_late,
(0 == sp->count) ? 0 : (sp->sum_late / sp->count));
}
}
return 0;
}
.help = "# Show alarm stats",
.next = LAST_COMMAND,
.param.simple_handler = cmd_stats
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_stats)
static int
cmd_dump (const char * command)
{
unsigned long now_tck;
unsigned int overflows;
int ai;
cprintf(
"Timer ticks %lu (0x%08lx) with %u overflows and %lu wakeups\n",
now_tck, now_tck, overflows, wakeups);
for (ai = 0; ai < nTimers; ++ai) {
if (NULL == ap) {
cprintf(
"\tcc %u is not available\n", ai);
} else {
cprintf(
"\tcc %u, flg 0x%02x, setting %lu ; CCTL %04x CCR %04x\n",
}
}
return 0;
}
.help = "# Show alarm internals",
.next = LAST_COMMAND,
.param.simple_handler = cmd_dump
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_dump)
static int
void * param,
const char * command,
size_t command_len)
{
unsigned long when_tck;
int rv;
if (0 == rv) {
unsigned long ms = (when_tck * 1000) / alarm_Hz;
unsigned long us = (when_tck * 1000) / (alarm_Hz / 1000);
cprintf(
"%lu tt at %lu Hz = %lu ms = %lu us\n", when_tck, alarm_Hz, ms, us);
}
return rv;
}
.help = "{tt} # show tt value in human time",
.next = LAST_COMMAND,
.handler = cmd_convert
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_convert)
static int
cmd_clocks (const char * argstr)
{
unsigned long now_tck;
unsigned long timer_overhead;
#if (BSP430_PMM_SUPPORTS_SVSM - 0)
int fast_wakeup = 0;
#endif
cprintf(
"CPU clocks (Hz): MCLK %lu ; SMCLK %lu ; ACLK %lu\n",
do {
unsigned long t0;
timer_overhead = now_tck - t0;
#if (BSP430_PMM_SUPPORTS_SVSM - 0)
#endif
} while (0);
cprintf(
"\tResolution %lu ns/tt, overhead %lu tt @ 32bit\n",
1000000000UL/alarm_Hz, timer_overhead);
#if (BSP430_PMM_SUPPORTS_SVSM - 0)
cprintf(
"PMM is %sconfigured for fast wakeup\n", fast_wakeup ?
"" :
"NOT ");
#endif
return 0;
}
.help = "# Clock/timer information",
.next = LAST_COMMAND,
.param.simple_handler = cmd_clocks
};
#undef LAST_COMMAND
#define LAST_COMMAND &dcmd_clocks
static int
cmd_uptime (const char * command)
{
return 0;
}
.help = "# Show system uptime",
.next = LAST_COMMAND,
.param.simple_handler = cmd_uptime
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_uptime)
static int
void * param,
const char * command,
size_t command_len)
{
return 0;
}
.help = "[cmd] # Show help on cmd or all commands",
.next = LAST_COMMAND,
.handler = cmd_help
};
#undef LAST_COMMAND
#define LAST_COMMAND (&dcmd_help)
void main ()
{
const char * command;
int flags;
int ai;
cprintf(
"alarm: " __DATE__
" " __TIME__
"\n");
#if 0 && (BSP430_PMM_SUPPORTS_SVSM - 0)
#endif
if (! alarmHAL_) {
cprintf(
"ERROR -- Timer not available\n");
return;
}
alarmHAL_->
hpl->
ctl = APP_TASSEL |
MC_2 | TACLR | TAIE;
if (nTimers > MAX_TIMERS) {
nTimers = MAX_TIMERS;
}
for (ai = 0; ai < nTimers; ++ai) {
}
cprintf(
"Alarm testing with timer %s having %u CCs\n",
cmd_clocks("");
commandSet = LAST_COMMAND;
command = NULL;
wakeups = 0;
while (1) {
flags &= ~eBSP430cliConsole_DO_COMPLETION;
}
int rv;
if (0 != rv) {
cprintf(
"Command execution returned %d\n", rv);
}
command = NULL;
}
cprintf(
"\r> %s", command ? command :
"");
flags &= ~eBSP430cliConsole_REPAINT;
}
flags &= ~eBSP430cliConsole_REPAINT_BEL;
}
if (flags & eBSP430cliConsole_READY) {
flags &= ~eBSP430cliConsole_READY;
}
do {
if (0 == flags) {
}
if (0 == flags) {
++wakeups;
}
} while (! flags);
}
}