Commit e2e7d59a authored by Alessandro Rubini's avatar Alessandro Rubini

temperature: add a temperature framework

This commit adds data structures, methods and a process to manage
temperature.  Currently the only temperature being read is the onewire
thermometer, so there is no difference with what we had before.
The cost is 1.1 kB in binary size.

Well, there is a difference: only the stat engine was reading
temperature, while now the thermometer is read continuously (every 15
seconds, or another Kconfig-urable interval).  This takes quite some
CPU time (18.5ms per polling loop, but allows any user to read
temperature (using the API we now provide) without re-reading the
onewire bus.

The real aim of this is monitoring a board-specific set of sensors,
as implemented and show in the next commit.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 3e630d08
......@@ -26,6 +26,10 @@ config RAMSIZE
default 65536 if WR_SWITCH
default 131072
config TEMP_POLL_INTERVAL
int
default 15
config PLL_VERBOSE
boolean
default y if WR_SWITCH
......@@ -188,6 +192,10 @@ config PRINT_BUFSIZE
also constraints the maximum lenght of text that can be written
in a single call to printf.
config TEMP_POLL_INTERVAL
depends on DEVELOPER && WR_NODE
int "Poll interval, in seconds, for temperature sensors"
config CMD_LL
depends on DEVELOPER && WR_NODE
bool "Build low-level commands for development/testing"
......
......@@ -2,6 +2,7 @@ obj-$(CONFIG_WR_NODE) += \
dev/endpoint.o \
dev/ep_pfilter.o \
dev/i2c.o \
dev/temperature.o \
dev/minic.o \
dev/pps_gen.o \
dev/syscon.o \
......@@ -17,6 +18,7 @@ obj-$(CONFIG_SDB_STORAGE) += dev/sdb-storage.o
obj-$(CONFIG_W1) += dev/w1.o dev/w1-hw.o dev/w1-shell.o
obj-$(CONFIG_W1) += dev/w1-temp.o dev/w1-eeprom.o
obj-$(CONFIG_W1) += dev/temp-w1.o
obj-$(CONFIG_UART) += dev/uart.o
obj-$(CONFIG_UART_SW) += dev/uart-sw.o
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2016 GSI (www.gsi.de)
* Author: Alessandro rubini
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <wrc.h>
#include <w1.h>
#include <temperature.h>
static struct wrc_onetemp temp_w1_data[] = {
{"pcb", TEMP_INVALID},
{NULL,}
};
static unsigned long nextt;
static int niterations;
/* Returns 1 if it did something */
static int temp_w1_refresh(struct wrc_temp *t)
{
static int done;
if (!done) {
nextt = timer_get_tics() + 1000;
done++;
}
/* Odd iterations: send the command, even iterations: read back */
int phase = niterations & 1;
static int intervals[] = {
200, (1000 * CONFIG_TEMP_POLL_INTERVAL) - 200
};
if (time_before(timer_get_tics(), nextt))
return 0;
nextt += intervals[phase];
niterations++;
switch(phase) {
case 0:
w1_read_temp_bus(&wrpc_w1_bus, W1_FLAG_NOWAIT);
break;
case 1:
temp_w1_data[0].t =
w1_read_temp_bus(&wrpc_w1_bus, W1_FLAG_COLLECT);
break;
}
return 1;
}
/* not static at this point, because it's the only one */
struct wrc_temp temp_w1 = {
.read = temp_w1_refresh,
.t = temp_w1_data,
};
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2016 GSI (www.gsi.de)
* Author: Alessandro rubini
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <wrc.h>
#include <string.h>
#include <temperature.h>
#include <shell.h>
extern struct wrc_temp temp_w1; /* The only one by now */
/*
* Library functions
*/
uint32_t wrc_temp_get(char *name)
{
struct wrc_onetemp *wt = temp_w1.t;
for (; wt->name; wt++) {
if (!strcmp(wt->name, name))
return wt->t;
}
return TEMP_INVALID;
}
struct wrc_onetemp *wrc_temp_getnext(struct wrc_onetemp *pt)
{
if (!pt) /* first one */
return temp_w1.t;
if (pt[1].name)
return pt + 1;
/* get next array, if any -- none by now */
return NULL;
}
extern int wrc_temp_format(char *buffer, int len)
{
struct wrc_onetemp *p;
int l = 0, i = 0;
int32_t t;
for (p = wrc_temp_getnext(NULL); p; p = wrc_temp_getnext(p), i++) {
if (l + 16 > len) {
l += sprintf(buffer + l, " ENOSPC");
return l;
}
t = p->t;
l += sprintf(buffer + l, "%s%s:", i ? " " : "", p->name);
if (t == TEMP_INVALID) {
l += sprintf(buffer + l, "INVALID");
continue;
}
if (t < 0) {
t = -(signed)t;
l += sprintf(buffer + l, "-");
}
l += sprintf(buffer + l,"%d.%04d", t >> 16,
((t & 0xffff) * 10 * 1000 >> 16));
}
return l;
}
/*
* The task
*/
void wrc_temp_init(void)
{
/* Call all actors, so they can init themselves (using ->data) */
temp_w1.read(&temp_w1);
}
int wrc_temp_refresh(void)
{
return temp_w1.read(&temp_w1);
}
/*
* The shell command
*/
static int cmd_temp(const char *args[])
{
char buffer[80];
wrc_temp_format(buffer, sizeof(buffer));
pp_printf("%s\n", buffer);
return 0;
}
DEFINE_WRC_COMMAND(temp) = {
.name = "temp",
.exec = cmd_temp,
};
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2016 GSI (www.gsi.de)
* Author: Alessandro rubini
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __TEMPERATURE_H__
#define __TEMPERATURE_H__
struct wrc_onetemp {
char *name;
int32_t t; /* fixed point, 16.16 (signed!) */
};
#define TEMP_INVALID (0x8000 << 16)
struct wrc_temp {
int (*read)(struct wrc_temp *);
void *data;
struct wrc_onetemp *t; /* zero-terminated */
};
/* the task */
extern void wrc_temp_init(void);
extern int wrc_temp_refresh(void);
/* lib functions */
extern uint32_t wrc_temp_get(char *name);
struct wrc_onetemp *wrc_temp_getnext(struct wrc_onetemp *);
extern int wrc_temp_format(char *buffer, int len);
#endif /* __TEMPERATURE_H__ */
......@@ -18,6 +18,7 @@
#include <syscon.h>
#include <pps_gen.h>
#include <onewire.h>
#include <temperature.h>
#include "wrc_ptp.h"
#include "hal_exports.h"
#include "lib/ipv4.h"
......@@ -350,11 +351,7 @@ int wrc_log_stats(void)
if (1) {
int32_t temp;
//first read the value from previous measurement,
//first one will be random, I know
temp = w1_read_temp_bus(&wrpc_w1_bus, W1_FLAG_COLLECT);
//then initiate new conversion for next loop cycle
w1_read_temp_bus(&wrpc_w1_bus, W1_FLAG_NOWAIT);
temp = wrc_temp_get("pcb");
pp_printf("temp: %d.%04d C", temp >> 16,
(int)((temp & 0xffff) * 10 * 1000 >> 16));
}
......
......@@ -14,6 +14,7 @@
#include <wrc.h>
#include <w1.h>
#include <temperature.h>
#include "syscon.h"
#include "uart.h"
#include "endpoint.h"
......@@ -210,6 +211,10 @@ struct wrc_task wrc_tasks[] = {
}, {
.name = "spll-bh",
.job = spll_update,
}, {
.name = "temperature",
.init = wrc_temp_init,
.job = wrc_temp_refresh,
#ifdef CONFIG_IP
}, {
.name = "ipv4",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment