wrc_main.c 5.36 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"
Grzegorz Daniluk's avatar
Grzegorz Daniluk committed
33

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

37
int wrc_ui_mode = UI_SHELL_MODE;
38
int wrc_ui_refperiod = TICS_PER_SECOND; /* 1 sec */
39
int wrc_phase_tracking = 1;
40

41
uint32_t cal_phase_transition = 2389;
42

43 44
int wrc_vlan_number = CONFIG_VLAN_NR;

45 46
static uint32_t prev_nanos_for_profile;

47
static void wrc_initialize(void)
48
{
49
	uint8_t mac_addr[6];
50

51
	sdb_find_devices();
52 53
	uart_init_sw();
	uart_init_hw();
54

55
	pp_printf("WR Core: starting up...\n");
56

57
	timer_init(1);
58
	wrpc_w1_init();
59 60
	wrpc_w1_bus.detail = ONEWIRE_PORT;
	w1_scan_bus(&wrpc_w1_bus);
61

62 63
	/*initialize flash*/
	flash_init();
64 65
	/*initialize I2C bus*/
	mi2c_init(WRPC_FMC_I2C);
66 67
	/*init storage (Flash / W1 EEPROM / I2C EEPROM*/
	storage_init(WRPC_FMC_I2C, FMC_EEPROM_ADR);
68

69
	if (get_persistent_mac(ONEWIRE_PORT, mac_addr) == -1) {
70
		pp_printf("Unable to determine MAC address\n");
71 72 73 74 75 76
		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;	//
77
	}
78

79 80 81
	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]);
82

83 84
	ep_init(mac_addr);
	ep_enable(1, 1);
Tomasz Wlostowski's avatar
Tomasz Wlostowski committed
85

86
	minic_init();
87
	shw_pps_gen_init();
88
	wrc_ptp_init();
89 90
	//try reading t24 phase transition from EEPROM
	calib_t24p(WRC_MODE_MASTER, &cal_phase_transition);
91
	spll_very_init();
92 93 94 95 96 97 98 99
	usleep_init();
	shell_init();

	wrc_ui_mode = UI_SHELL_MODE;
	_endram = ENDRAM_MAGIC;

	wrc_ptp_set_mode(WRC_MODE_SLAVE);
	wrc_ptp_start();
100
	shw_pps_gen_get_time(NULL, &prev_nanos_for_profile);
101
}
102

103 104 105 106 107
DEFINE_WRC_TASK0(idle) = {
	.name = "idle",
	.init = wrc_initialize,
};

108 109
int link_status;

110
static int wrc_check_link(void)
111
{
112
	static int prev_state = 0;
113
	int state = ep_link_up(NULL);
114 115
	int rv = 0;

116
	if (!prev_state && state) {
117
		wrc_verbose("Link up.\n");
118
		gpio_out(GPIO_LED_LINK, 1);
119
		sfp_match();
120
		wrc_ptp_start();
121 122 123
		link_status = LINK_WENT_UP;
		rv = 1;
	} else if (prev_state && !state) {
124
		wrc_verbose("Link down.\n");
125
		gpio_out(GPIO_LED_LINK, 0);
126
		link_status = LINK_WENT_DOWN;
127
		wrc_ptp_stop();
128 129 130 131 132
		rv = 1;
		/* special case */
		spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
		shw_pps_gen_enable_output(0);

133
	} else
134 135
		link_status = (state ? LINK_UP : LINK_DOWN);
	prev_state = state;
136 137

	return rv;
138
}
139 140 141 142
DEFINE_WRC_TASK(link) = {
	.name = "check-link",
	.job = wrc_check_link,
};
143

144
static int ui_update(void)
145
{
146
	int ret;
147

148
	if (wrc_ui_mode == UI_GUI_MODE) {
149
		ret = wrc_mon_gui();
150
		if (uart_read_byte() == 27 || wrc_ui_refperiod == 0) {
151 152
			shell_init();
			wrc_ui_mode = UI_SHELL_MODE;
153
		}
154
	} else {
155
		ret = shell_interactive();
156
	}
157
	return ret;
158
}
159

160 161
/* initialize functions to be called after reset in check_reset function */
void init_hw_after_reset(void)
162
{
163 164
	/* Ok, now init the devices so we can printf and delay */
	sdb_find_devices();
165 166
	uart_init_sw();
	uart_init_hw();
167 168 169
	timer_init(1);
}

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
/* 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;
}
192 193 194 195
DEFINE_WRC_TASK(uptime) = {
	.name = "uptime",
	.init = init_uptime,
	.job = update_uptime,
196 197
};

198 199 200 201 202 203 204 205 206 207 208 209 210
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,
};
211

212 213 214 215 216 217 218
/* 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;

	if (!done_sth)
219
		t = __task_begin; /* task 0 is special */
220 221 222 223 224 225 226 227 228 229 230 231 232 233
	shw_pps_gen_get_time(NULL, &nanos);
	delta = nanos - prev_nanos_for_profile;
	if (delta < 0)
		delta += 1000 * 1000 * 1000;

	t->nanos += delta;
	if (t-> nanos > 1000 * 1000 * 1000) {
		t->nanos -= 1000 * 1000 * 1000;
		t->seconds++;
	}
	prev_nanos_for_profile = nanos;
}

/* Run a task with profiling */
234
static void wrc_run_task(struct wrc_task *t)
235
{
236 237 238 239 240 241 242 243 244 245
	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);
246 247
}

248
int main(void) __attribute__ ((weak));
249 250
int main(void)
{
251
	struct wrc_task *t;
252

253
	check_reset();
254

255
	/* initialization of individual tasks */
256 257 258
	for_each_task(t)
		if (t->init)
			t->init();
259

260
	for (;;) {
261 262
		for_each_task(t)
			wrc_run_task(t);
263 264

		/* better safe than sorry */
265
		check_stack();
266
	}
267
}