55 #include "contiki-net.h"
56 #include "sys/clock.h"
58 #include "dev/watchdog.h"
65 #define DEBUG DEBUG_NONE
68 #if BATMON_CONF_ENABLED
69 void batmon_log(uint8_t trigger);
71 #define LOG_TRIGGER_OAP_DISCO_START 0x01
72 #define LOG_TRIGGER_OAP_DISCO_DONE 0x02
73 #define LOG_TRIGGER_OAP_DISCO_ABORT 0x03
75 #define batmon_log(t) do { } while(0);
79 static struct disco_request_pdu *req;
80 static struct disco_response_pdu resp;
81 static struct disco_seed seed;
83 static uint8_t sector;
84 static uint16_t interval;
85 static struct ctimer disco_timer;
87 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
88 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
93 __xdata
__at(BOOTTY_CMD_LOCATION) static uint8_t bd;
95 static
void timer_handler(
void *p);
101 n740_analog_deactivate();
103 n740_analog_activate();
104 state = DISCO_STATE_LISTENING;
105 memset(&seed, 0,
sizeof(seed));
107 batmon_log(LOG_TRIGGER_OAP_DISCO_ABORT);
111 restart_timer(uint16_t t) CC_NON_BANKED
115 ctimer_set(&disco_timer, interval, timer_handler, &state);
119 timer_handler(
void *p)
126 if(*s == DISCO_STATE_PREPARING) {
127 n740_analog_deactivate();
129 n740_analog_activate();
132 restart_timer(DISCO_TIMEOUT_PREPARE);
134 PRINTF(
"Disco: Erased %u\n", sector);
135 if((sector & 1) == 0) {
137 PRINTF(
"Disco: Next %u\n", sector);
138 n740_analog_deactivate();
140 n740_analog_activate();
141 restart_timer(DISCO_TIMEOUT_PREPARE);
143 PRINTF(
"Disco: Ready\n");
144 *s = DISCO_STATE_READY;
145 resp.status = DISCO_CMD_INIT;
146 restart_timer(DISCO_TIMEOUT_ABORT);
147 server_conn->
rport = seed.port;
149 uip_udp_packet_send(server_conn, &resp, DISCO_RESP_LEN_INIT);
153 server_conn->
rport = 0;
156 }
else if(*s == DISCO_STATE_READY) {
158 }
else if(*s == DISCO_STATE_REBOOTING) {
164 is_protected(uint8_t a) CC_NON_BANKED
169 return SECTOR_PROTECTED;
174 if(a >= (32 - (1 << bp))) {
175 return SECTOR_PROTECTED;
177 return SECTOR_UNPROTECTED;
181 cmd_init() CC_NON_BANKED
183 PRINTF(
"Disco: Init 0x%02x\n", req->addr[0]);
186 resp.status = DISCO_ERR_BAD_LEN;
187 return DISCO_RESP_LEN_ERR;
189 n740_analog_deactivate();
191 sector = 2 * req->addr[0];
192 if(is_protected(sector) == SECTOR_PROTECTED
193 || is_protected(sector + 1) == SECTOR_PROTECTED) {
194 resp.status = DISCO_ERR_PROTECTED;
195 n740_analog_activate();
196 return DISCO_RESP_LEN_ERR;
199 n740_analog_activate();
200 state = DISCO_STATE_PREPARING;
201 restart_timer(DISCO_TIMEOUT_PREPARE);
204 seed.port = UIP_UDP_BUF->srcport;
206 PRINTF(
"Disco: OK\n");
208 batmon_log(LOG_TRIGGER_OAP_DISCO_START);
210 return DISCO_RESPONSE_NONE;
214 cmd_write() CC_NON_BANKED
216 PRINTF(
"Disco: Write 0x%02x%02x%02x\n", req->addr[0], req->addr[1],
219 resp.status = DISCO_ERR_BAD_LEN;
220 return DISCO_RESP_LEN_ERR;
222 restart_timer(DISCO_TIMEOUT_ABORT);
223 n740_analog_deactivate();
224 m25p16_pp(req->addr, req->data, DISCO_FLEN_DATA);
227 n740_analog_activate();
228 resp.status = DISCO_CMD_WRITE;
229 memcpy(resp.addr, req->addr, DISCO_FLEN_ADDR);
230 return DISCO_RESP_LEN_WRITE;
234 cmd_switch() CC_NON_BANKED
236 PRINTF(
"Disco: Switch 0x%02x\n", req->addr[0]);
238 resp.status = DISCO_ERR_BAD_LEN;
239 return DISCO_RESP_LEN_ERR;
241 if(req->addr[0] > 15) {
242 resp.status = DISCO_ERR_BAD_OFFSET;
243 return DISCO_RESP_LEN_ERR;
246 bd = BOOTTY_CMD_COPY_IMAGE;
249 resp.status = DISCO_CMD_SWITCH;
250 resp.addr[0] = req->addr[0];
252 restart_timer(DISCO_TIMEOUT_REBOOT);
253 state = DISCO_STATE_REBOOTING;
255 return DISCO_RESP_LEN_SWITCH;
259 cmd_done() CC_NON_BANKED
261 PRINTF(
"Disco: Done\n");
263 resp.status = DISCO_ERR_BAD_LEN;
264 return DISCO_RESP_LEN_ERR;
266 resp.status = DISCO_CMD_DONE;
268 batmon_log(LOG_TRIGGER_OAP_DISCO_DONE);
270 return DISCO_RESP_LEN_DONE;
274 event_handler(process_event_t ev) CC_NON_BANKED
276 uint8_t rv = DISCO_RESPONSE_NONE;
283 if(req->cmd == DISCO_CMD_DONE) {
288 if(req->cmd == DISCO_CMD_SWITCH) {
293 case DISCO_STATE_LISTENING:
295 if(req->cmd == DISCO_CMD_INIT) {
299 case DISCO_STATE_PREPARING:
300 PRINTF(
"Disco: Not Ready\n");
301 resp.status = DISCO_ERR_NOT_READY;
302 rv = DISCO_RESP_LEN_ERR;
304 case DISCO_STATE_READY:
306 if(req->cmd == DISCO_CMD_WRITE) {
308 }
else if(req->cmd == DISCO_CMD_INIT) {
309 resp.status = DISCO_ERR_INIT_DONE;
310 rv = DISCO_RESP_LEN_ERR;
311 }
else if(req->cmd == DISCO_CMD_SWITCH) {
319 PROCESS(disco_process,
"Disco Server Process");
327 PRINTF(
"Disco Server\n");
332 state = DISCO_STATE_LISTENING;
336 len = event_handler(ev);
339 server_conn->
rport = UIP_UDP_BUF->srcport;
341 uip_udp_packet_send(server_conn, &resp, len);
344 server_conn->
rport = 0;
#define uip_create_unspecified(a)
set IP address a to unspecified
uip_len
The length of the packet in the uip_buf buffer.
uint16_t rport
The remote port number in network byte order.
#define PROCESS_BEGIN()
Define the beginning of a process.
CCIF struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
Header file for the Disco server (embedded part of the DISCOBALL project) ...
#define NULL
The null pointer.
Header file for the control of the M25P16 on sensinode N740s.
void m25p16_pp(uint8_t *addr, uint8_t *buff, uint8_t buff_len)
Program Page (PP) instruction.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
void watchdog_reboot(void)
Keeps control until the WDT throws a reset signal.
uip_ipaddr_t ripaddr
The IP address of the remote peer.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define UIP_IP_BUF
Pointer to IP header.
#define PROCESS_END()
Define the end of a process.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Header File for the module which controls the Sensinode N740 8-bit serial-in/serial or parall...
void watchdog_periodic(void)
Writes the WDT clear sequence.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define M25P16_BP()
Retrieve Block Protect Bits from the status register.
#define PROCESS(name, strname)
Declare a process.
Header file for the callback timer
void m25p16_dp()
Deep Power Down (DP) instruction.
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
process_event_t tcpip_event
The uIP event.
#define PROCESS_YIELD()
Yield the currently running process.
void m25p16_se(uint8_t s)
Sector Erase (SE) instruction.
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
A set of debugging macros.
Representation of a uIP UDP connection.
__xdata __at(0x0000)
Each iteration is ~1.0xy usec, so this function delays for roughly len usec.
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
#define M25P16_WIP()
Check for Write in Progress.
uip_appdata
Pointer to the application data in the packet buffer.
void m25p16_res()
Release from Deep Power Down (RES) instruction.