wrc_main.c 6.61 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * This work is part of the White Rabbit project
 *
 * Copyright (C) 2011,2012 CERN (www.cern.ch)
 * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
 * Author: Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 */
10 11 12
#include <stdio.h>
#include <inttypes.h>

13 14
#include <stdarg.h>

15
#include <wrc.h>
16
#include <w1.h>
17
#include <temperature.h>
18
#include "syscon.h"
19 20 21 22
#include "uart.h"
#include "endpoint.h"
#include "minic.h"
#include "pps_gen.h"
23
#include "ptpd_netif.h"
Grzegorz Daniluk's avatar
Grzegorz Daniluk committed
24
#include "i2c.h"
25
#include "storage.h"
26
#include "softpll_ng.h"
27
#include "onewire.h"
28
#include "pps_gen.h"
29
#include "shell.h"
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
30
#include "lib/ipv4.h"
31
#include "rxts_calibrator.h"
32
#include "flash.h"
33
#include "fram.h"
Grzegorz Daniluk's avatar
Grzegorz Daniluk committed
34

35
#include "wrc_ptp.h"
36
#include "system_checks.h"
37

38 39 40 41
#ifndef CONFIG_DEFAULT_PRINT_TASK_TIME_THRESHOLD
#define CONFIG_DEFAULT_PRINT_TASK_TIME_THRESHOLD 0
#endif

42
int wrc_ui_mode = UI_SHELL_MODE;
43
int wrc_ui_refperiod = TICS_PER_SECOND; /* 1 sec */
44
int wrc_phase_tracking = 1;
45
char wrc_hw_name[HW_NAME_LENGTH];
46

47
uint32_t cal_phase_transition = 2389;
48

49 50
int wrc_vlan_number = CONFIG_VLAN_NR;

51
static uint32_t prev_nanos_for_profile;
52
static uint32_t prev_ticks_for_profile;
53
uint32_t print_task_time_threshold = CONFIG_DEFAULT_PRINT_TASK_TIME_THRESHOLD;
54

55
static void wrc_initialize(void)
56
{
57
	uint8_t mac_addr[6];
58

59
	sdb_find_devices();
60
	uart_init_hw();
61

62
	pp_printf("WR Core: starting up...\n");
63

64
	timer_init(1);
65
	get_hw_name(wrc_hw_name);
66 67 68 69

	if (HAS_GENSDBFS)
		storage_read_hdl_cfg();

70
	wrpc_w1_init();
71 72
	wrpc_w1_bus.detail = ONEWIRE_PORT;
	w1_scan_bus(&wrpc_w1_bus);
73

74 75
	/*initialize flash*/
	flash_init();
76 77
	/*initialize I2C bus*/
	mi2c_init(WRPC_FMC_I2C);
78 79
	/*init storage (Flash / W1 EEPROM / I2C EEPROM*/
	storage_init(WRPC_FMC_I2C, FMC_EEPROM_ADR);
80

81
	if (get_persistent_mac(ONEWIRE_PORT, mac_addr) == -1) {
82
		pp_printf("Unable to determine MAC address\n");
Grzegorz Daniluk's avatar
Grzegorz Daniluk committed
83 84 85 86 87 88
		mac_addr[0] = 0x22;	/*
		mac_addr[1] = 0x33;	*
		mac_addr[2] = 0x44;	* fallback MAC if get_persistent_mac fails
		mac_addr[3] = 0x55;	*
		mac_addr[4] = 0x66;	*
		mac_addr[5] = 0x77;	*/
89
	}
90

91 92 93
	pp_printf("Local MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
		mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
		mac_addr[4], mac_addr[5]);
94

95
	net_rst();
96
	ep_init(mac_addr);
97 98 99
	/* Sleep for 1s to make sure WRS v4.2 always realizes that
	 * the link is down */
	timer_delay_ms(200);
100
	ep_enable(1, 1);
Tomasz Wlostowski's avatar
Tomasz Wlostowski committed
101

102
	minic_init();
103
	shw_pps_gen_init();
104
	wrc_ptp_init();
Grzegorz Daniluk's avatar
Grzegorz Daniluk committed
105
	/* try reading t24 phase transition from EEPROM */
106
	calib_t24p(WRC_MODE_MASTER, &cal_phase_transition);
107
	spll_very_init();
108 109 110 111 112 113 114 115
	usleep_init();
	shell_init();

	wrc_ui_mode = UI_SHELL_MODE;
	_endram = ENDRAM_MAGIC;

	wrc_ptp_set_mode(WRC_MODE_SLAVE);
	wrc_ptp_start();
116
	shw_pps_gen_get_time(NULL, &prev_nanos_for_profile);
117 118
	/* get tics */
	prev_ticks_for_profile = timer_get_tics();
119
}
120

121 122 123 124 125
DEFINE_WRC_TASK0(idle) = {
	.name = "idle",
	.init = wrc_initialize,
};

126 127
int link_status;

128
static int wrc_check_link(void)
129
{
130
	static int prev_state = 0;
131
	int state = ep_link_up(NULL);
132 133
	int rv = 0;

134
	if (!prev_state && state) {
135
		wrc_verbose("Link up.\n");
136
		gpio_out(GPIO_LED_LINK, 1);
137
		sfp_match();
138
		wrc_ptp_start();
139 140 141
		link_status = LINK_WENT_UP;
		rv = 1;
	} else if (prev_state && !state) {
142
		wrc_verbose("Link down.\n");
143
		gpio_out(GPIO_LED_LINK, 0);
144
		link_status = LINK_WENT_DOWN;
145
		wrc_ptp_stop();
146 147 148 149 150
		rv = 1;
		/* special case */
		spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
		shw_pps_gen_enable_output(0);

151
	} else
152 153
		link_status = (state ? LINK_UP : LINK_DOWN);
	prev_state = state;
154 155

	return rv;
156
}
157 158 159 160
DEFINE_WRC_TASK(link) = {
	.name = "check-link",
	.job = wrc_check_link,
};
161

162
static int ui_update(void)
163
{
164
	int ret;
165

166
	if (wrc_ui_mode == UI_GUI_MODE) {
167
		ret = wrc_mon_gui();
168
		if (uart_read_byte() == 27 || wrc_ui_refperiod == 0) {
169 170
			shell_init();
			wrc_ui_mode = UI_SHELL_MODE;
171
		}
172
	} else {
173
		ret = shell_interactive();
174
	}
175
	return ret;
176
}
177

178 179
/* initialize functions to be called after reset in check_reset function */
void init_hw_after_reset(void)
180
{
181 182
	/* Ok, now init the devices so we can printf and delay */
	sdb_find_devices();
183
	uart_init_hw();
184 185 186
	timer_init(1);
}

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
/* count uptime, in seconds, for remote polling */
static uint32_t uptime_lastj;
static void init_uptime(void)
{
	uptime_lastj = timer_get_tics();
}
static int update_uptime(void)
{
	extern uint32_t uptime_sec;
	uint32_t j;
	static uint32_t fraction = 0;

	j = timer_get_tics();
	fraction += j - uptime_lastj;
	uptime_lastj = j;
	if (fraction > TICS_PER_SECOND) {
		fraction -= TICS_PER_SECOND;
		uptime_sec++;
		return 1;
	}
	return 0;
}
209 210 211 212
DEFINE_WRC_TASK(uptime) = {
	.name = "uptime",
	.init = init_uptime,
	.job = update_uptime,
213 214
};

215 216 217 218 219 220 221 222 223 224 225 226 227
DEFINE_WRC_TASK(ptp) = {
	.name = "ptp",
	.job = wrc_ptp_update,
};
DEFINE_WRC_TASK(shell) = {
	.name = "shell+gui",
	.init = shell_boot_script,
	.job = ui_update,
};
DEFINE_WRC_TASK(spll) = {
	.name = "spll-bh",
	.job = spll_update,
};
228

229 230 231 232 233 234 235 236
static void task_time_normalize(struct wrc_task *t)
{
	if (t->nanos > 1000 * 1000 * 1000) {
		t->nanos -= 1000 * 1000 * 1000;
		t->seconds++;
	}
}

237 238 239 240 241
/* Account the time to either this task or task 0 */
static void account_task(struct wrc_task *t, int done_sth)
{
	uint32_t nanos;
	signed int delta;
242 243
	uint32_t ticks;
	signed int delta_ticks;
244 245

	if (!done_sth)
246
		t = __task_begin; /* task 0 is special */
247
	shw_pps_gen_get_time(NULL, &nanos);
248 249 250
	/* get monotonic number of ticks */
	ticks = timer_get_tics();

251 252 253 254 255
	delta = nanos - prev_nanos_for_profile;
	if (delta < 0)
		delta += 1000 * 1000 * 1000;

	t->nanos += delta;
256
	task_time_normalize(t);
257 258 259 260 261 262 263 264 265
	prev_nanos_for_profile = nanos;

	delta_ticks = ticks - prev_ticks_for_profile;
	if (delta_ticks < 0)
		delta_ticks += TICS_PER_SECOND;

	if (t->max_run_ticks < delta_ticks) {/* update max_run_ticks */
		if (print_task_time_threshold) {
			/* Print only if threshold is set */
266 267
			pp_printf("New max run time for a task %s, old %ld, "
				  "new %d\n",
268
				  t->name, t->max_run_ticks, delta_ticks);
269
		}
270
		t->max_run_ticks = delta_ticks;
271
	}
272 273 274 275 276
	if (print_task_time_threshold
            && delta_ticks > print_task_time_threshold)
		pp_printf("task %s, run for %d ms\n", t->name, delta_ticks);

	prev_ticks_for_profile = ticks;
277 278 279
}

/* Run a task with profiling */
280
static void wrc_run_task(struct wrc_task *t)
281
{
282 283 284 285 286 287 288 289 290 291
	int done_sth = 0;

	if (!t->job) /* idle task, just count iterations */
		t->nrun++;
	else if (!t->enable || *t->enable) {
		/* either enabled or without a check variable */
		done_sth = t->job();
		t->nrun += done_sth;
	}
	account_task(t, done_sth);
292 293
}

294
int main(void) __attribute__ ((weak));
295 296
int main(void)
{
297
	struct wrc_task *t;
298

299
	check_reset();
300

301
	/* initialization of individual tasks */
302 303 304
	for_each_task(t)
		if (t->init)
			t->init();
305

306
	for (;;) {
307 308
		for_each_task(t)
			wrc_run_task(t);
309 310

		/* better safe than sorry */
311
		check_stack();
312
	}
313
}