Contiki-NG
uart-driver.c
1 /*
2  * Copyright (c) 2015 NXP B.V.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of NXP B.V. nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY NXP B.V. AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL NXP B.V. OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * Author: Lee Mitchell
32  * Integrated into Contiki by Beshr Al Nahas
33  *
34  */
35 
36 #include <jendefs.h>
37 
38 #ifdef DEBUG
39 #include <dbg.h>
40 #else
41 #define DBG_vPrintf(...)
42 #endif
43 
44 #include "contiki.h"
45 #include "uart-driver.h"
46 #include "sys/rtimer.h"
47 #include "watchdog.h"
48 #include <math.h>
49 #include <AppHardwareApi.h>
50 
51 #if UART_XONXOFF_FLOW_CTRL
52 
53 #include "sys/process.h"
54 
55 #define TX_FIFO_SW_FLOW_LIMIT 8 /* Maximum allowed fill level for tx fifo */
56 #if TX_FIFO_SW_FLOW_LIMIT > 16
57 #undef TX_FIFO_SW_FLOW_LIMIT
58 #define TX_FIFO_SW_FLOW_LIMIT 16
59 #warning "TX_FIFO_SW_FLOW_LIMIT too big. Forced to 16."
60 #endif /* TX_FIFO_SW_FLOW_LIMIT > 16 */
61 
62 #define XON 17
63 #define XOFF 19
64 
65 extern volatile unsigned char xonxoff_state;
66 
67 #endif /* UART_XONXOFF_FLOW_CTRL */
68 
69 #define DEBUG_UART_BUFFERED FALSE
70 
71 #define CHAR_DEADLINE (uart_char_delay * 100)
72 
73 /*** Local Function Prototypes ***/
74 static void uart_driver_isr(uint32_t device_id, uint32_t item_bitmap);
75 #if !UART_XONXOFF_FLOW_CTRL
76 static int16_t uart_driver_get_tx_fifo_available_space(uint8_t uart_dev);
77 #endif /* !UART_XONXOFF_FLOW_CTRL */
78 static void uart_driver_set_baudrate(uint8_t uart_dev, uint8_t br);
79 static void uart_driver_set_high_baudrate(uint8_t uart_dev, uint32_t baud_rate);
80 
81 /*** Local Variables ***/
82 #define UART_NUM_UARTS 2
83 static uint16_t tx_fifo_size[UART_NUM_UARTS] = { 0 };
84 static uint8_t active_uarts[UART_NUM_UARTS] = { 0 };
85 /** slip input function pointer */
86 static int(*uart_input[UART_NUM_UARTS]) (unsigned char) = { 0 };
87 /* time in uSec for transmitting 1 char */
88 static uint16_t uart_char_delay = 0;
89 static volatile int8_t interrupt_enabled[UART_NUM_UARTS] = { 0 };
90 static volatile int8_t interrupt_enabled_saved[UART_NUM_UARTS] = { 0 };
91 
92 /****************************************************************************
93  *
94  * NAME: uart_driver_init
95  *
96  * DESCRIPTION:
97  * Initializes the specified UART device.
98  *
99  * PARAMETERS: Name RW Usage
100  * uart_dev R UART to initialise, eg, E_AHI_UART_0
101  * br R Baudrate to use (e.g. UART_RATE_115200)
102  * if br > UART_RATE_115200
103  * then uart_driver_set_baud_rate is called
104  * else vAHI_UartSetClockDivisor
105  * txbuf_data R Pointer to a memory block to use
106  * and rxbuf_data as uart tx/rx fifo
107  * txbuf_size R size of tx fifo (valid range: 16-2047)
108  * txbuf_size R size of rx fifo (valid range: 16-2047)
109  * uart_input_function a function pointer to input uart rx bytes
110  * RETURNS:
111  * void
112  *
113  ****************************************************************************/
114 void
115 uart_driver_init(uint8_t uart_dev, uint8_t br, uint8_t *txbuf_data,
116  uint16_t txbuf_size, uint8_t *rxbuf_data, uint16_t rxbuf_size,
117  int (*uart_input_function)(unsigned char c))
118 {
119 #if !UART_HW_FLOW_CTRL
120  /* Disable RTS/CTS */
121  vAHI_UartSetRTSCTS(uart_dev, FALSE);
122 #endif
123 
124  tx_fifo_size[uart_dev] = txbuf_size;
125 
126  /* Configure the selected Uart */
127  uint8_t uart_enabled = bAHI_UartEnable(uart_dev, txbuf_data, txbuf_size,
128  rxbuf_data, rxbuf_size);
129  /* fallback to internal buffers */
130  if(!uart_enabled) {
131  vAHI_UartEnable(uart_dev);
132  tx_fifo_size[uart_dev] = 16; /* Fixed size */
133  }
134  /* Reset tx/rx fifos */
135  vAHI_UartReset(uart_dev, TRUE, TRUE);
136  vAHI_UartReset(uart_dev, FALSE, FALSE);
137 
138  uart_driver_set_baudrate(uart_dev, br);
139 
140  /* install interrupt service callback */
141  if(uart_dev == E_AHI_UART_0) {
142  vAHI_Uart0RegisterCallback((void *)uart_driver_isr);
143  } else {
144  vAHI_Uart1RegisterCallback((void *)uart_driver_isr);
145  /* Enable RX interrupt */
146  }
147  uart_driver_enable_interrupts(uart_dev);
148  uart_input[uart_dev] = uart_input_function;
149  active_uarts[uart_dev] = 1;
150 
151 #if UART_HW_FLOW_CTRL
152  /* Configure HW flow control */
153  vAHI_UartSetAutoFlowCtrl(uart_dev, E_AHI_UART_FIFO_ARTS_LEVEL_13, /* uint8 const u8RxFifoLevel,*/
154  FALSE, /* bool_t const bFlowCtrlPolarity,*/
155  TRUE, /* bool_t const bAutoRts, */
156  TRUE /* bool_t const bAutoCts */);
157 #endif
158 
159  DBG_vPrintf("UART %d init: using %s buffers %d\n", uart_dev,
160  uart_enabled ? "external" : "internal", tx_fifo_size[uart_dev]);
161 }
162 void
163 uart_driver_enable_interrupts(uint8_t uart_dev)
164 {
165  /* wait while char being tx is done */
166  while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
167 
168  vAHI_UartSetInterrupt(uart_dev, FALSE /*bEnableModemStatus*/,
169  FALSE /*bEnableRxLineStatus == Break condition */,
170  FALSE /*bEnableTxFifoEmpty*/,
171  TRUE /* bEnableRxData */, E_AHI_UART_FIFO_LEVEL_14);
172  interrupt_enabled[uart_dev] = 1;
173 }
174 void
175 uart_driver_disable_interrupts(uint8_t uart_dev)
176 {
177  /* wait while char being tx is done */
178  while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
179 
180  vAHI_UartSetInterrupt(uart_dev, FALSE /*bEnableModemStatus*/,
181  FALSE /*bEnableRxLineStatus == Break condition */,
182  FALSE /*bEnableTxFifoEmpty*/,
183  FALSE /* bEnableRxData */, E_AHI_UART_FIFO_LEVEL_14);
184  interrupt_enabled[uart_dev] = 0;
185 }
186 void
187 uart_driver_store_interrupts(uint8_t uart_dev)
188 {
189  interrupt_enabled_saved[uart_dev] = interrupt_enabled[uart_dev];
190 }
191 void
192 uart_driver_restore_interrupts(uint8_t uart_dev)
193 {
194  if(interrupt_enabled_saved[uart_dev]) {
195  uart_driver_enable_interrupts(uart_dev);
196  } else {
197  uart_driver_disable_interrupts(uart_dev);
198  }
199 }
200 int8_t
201 uart_driver_interrupt_is_enabled(uint8_t uart_dev)
202 {
203  return interrupt_enabled[uart_dev];
204 }
205 void
206 uart_driver_set_input(uint8_t uart_dev, int
207  (*uart_input_function)(unsigned char c))
208 {
209  uart_input[uart_dev] = uart_input_function;
210 }
211 /****************************************************************************
212  *
213  * NAME: uart_driver_read
214  *
215  * DESCRIPTION:
216  * Reads 1 byte from the RX buffer. If there is no data in the
217  * buffer, then return FALSE
218  *
219  * PARAMETERS: Name RW Usage
220  * uart_dev R UART to use, eg, E_AHI_UART_0
221  *
222  * RETURNS:
223  * TRUE if a byte has been read from the queue
224  *
225  ****************************************************************************/
226 uint8_t
227 uart_driver_read(uint8_t uart_dev, uint8_t *data)
228 {
229  if(data && u16AHI_UartReadRxFifoLevel(uart_dev) > 0) {
230  *data = u8AHI_UartReadData(uart_dev);
231  return TRUE;
232  }
233  return FALSE;
234 }
235 void
236 uart_driver_write_buffered(uint8_t uart_dev, uint8_t ch)
237 {
238  uart_driver_write_with_deadline(uart_dev, ch);
239 }
240 /****************************************************************************
241  *
242  * NAME: uart_driver_write_with_deadline
243  *
244  * DESCRIPTION:
245  * Writes one byte to the specified uart for transmission
246  *
247  * PARAMETERS: Name RW Usage
248  * uart_dev R UART to use, eg, E_AHI_UART_0
249  * ch R data to transmit
250  *
251  * RETURNS:
252  * void
253  *
254  ****************************************************************************/
255 void
256 uart_driver_write_with_deadline(uint8_t uart_dev, uint8_t ch)
257 {
258 #if UART_XONXOFF_FLOW_CTRL
259  /* Block until host can receive data */
260  /* Wait until there are less than N characters in TX FIFO */
261  while(xonxoff_state != XON
262  || u16AHI_UartReadTxFifoLevel(uart_dev) > TX_FIFO_SW_FLOW_LIMIT) {
264  }
265  /* write to TX FIFO and return immediately */
266  vAHI_UartWriteData(uart_dev, ch);
267 #else /* UART_XONXOFF_FLOW_CTRL */
268  volatile int16_t write = 0;
270  /* wait until there is space in tx fifo */
271  RTIMER_BUSYWAIT_UNTIL(write = (uart_driver_get_tx_fifo_available_space(uart_dev) > 0),
272  CHAR_DEADLINE);
273  /* write only if there is space so we do not get stuck */
274  if(write) {
275  /* write to TX FIFO and return immediately */
276  vAHI_UartWriteData(uart_dev, ch);
277  }
278 #endif /* UART_XONXOFF_FLOW_CTRL */
279 }
280 void
281 uart_driver_write_direct(uint8_t uart_dev, uint8_t ch)
282 {
283  /* Write character */
284  vAHI_UartWriteData(uart_dev, ch);
285  /* Wait for buffers to empty */
286  while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_THRE) == 0) ;
287  while((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_TEMT) == 0) ;
288 }
289 /****************************************************************************
290  *
291  * NAME: uart_driver_rx_handler
292  *
293  * DESCRIPTION:
294  * Interrupt service callback for UART data reception. Reads a received
295  * byte from the UART and writes it to the reception buffer if it is not
296  * full.
297  *
298  * PARAMETERS: Name RW Usage
299  * uart_dev R Uart to read from
300  *
301  * RETURNS:
302  * void
303  *
304  ****************************************************************************/
305 void
306 uart_driver_rx_handler(uint8_t uart_dev)
307 {
308  /* optimization for high throughput: Read upto 32 bytes from RX fifo.
309  * Disabled because it does not work with current slip_input_byte */
310 
311  /* Status from uart_input:
312  * 0 means do not exit power saving mode
313  * -1 means RX buffer overflow ==> stop reading
314  * 1 means end of slip packet
315  */
316 #if UART_XONXOFF_FLOW_CTRL
317  /* save old status */
318  int xonxoff_state_old = xonxoff_state;
319 #endif /* UART_XONXOFF_FLOW_CTRL */
320  int status = 0;
321  int c = 0;
322  while(u16AHI_UartReadRxFifoLevel(uart_dev) > 0 && c++ < 32 && status == 0) {
323  if(uart_input[uart_dev] != NULL) { /* read one char at a time */
324 
325  /* process received character */
326  status = (uart_input[uart_dev])(u8AHI_UartReadData(uart_dev));
327 
328 #if UART_XONXOFF_FLOW_CTRL
329  /* Process XON-XOFF*/
330  if(xonxoff_state == XOFF) {
331  /* XXX do not set break condition as it corrupts one character, instead we block on TX */
332  /* Instruct uart to stop TX */
333  /* vAHI_UartSetBreak(uart_dev, TRUE); */
334  break;
335  } else if(xonxoff_state_old == XOFF && xonxoff_state == XON) {
336  /* Instruct uart to resume TX if it was stopped */
337  /* vAHI_UartSetBreak(uart_dev, FALSE); */
338  }
339 #endif /* UART_XONXOFF_FLOW_CTRL */
340  } else {
341  /* no input handler, or no bytes to read: Discard byte. */
342  u8AHI_UartReadData(uart_dev);
343  }
344  }
345 }
346 /****************************************************************************/
347 /*** Local Functions ***/
348 /****************************************************************************/
349 
350 #if !UART_XONXOFF_FLOW_CTRL
351 /* Returns the free space in tx fifo, i.e., how many characters we can put */
352 static int16_t
353 uart_driver_get_tx_fifo_available_space(uint8_t uart_dev)
354 {
355  return tx_fifo_size[uart_dev] - u16AHI_UartReadTxFifoLevel(uart_dev);
356 }
357 #endif /* !UART_XONXOFF_FLOW_CTRL */
358 /* Initializes the specified UART with auto-selection of
359  baudrate tuning method */
360 static void
361 uart_driver_set_baudrate(uint8_t uart_dev, uint8_t br)
362 {
363  uint32_t high_br = 0;
364  uint8_t low_br = 0;
365 
366  switch(br) {
367  case UART_RATE_4800:
368  low_br = E_AHI_UART_RATE_4800;
369  uart_char_delay = 1667;
370  break;
371  case UART_RATE_9600:
372  low_br = E_AHI_UART_RATE_9600;
373  uart_char_delay = 834;
374  break;
375  case UART_RATE_19200:
376  low_br = E_AHI_UART_RATE_19200;
377  uart_char_delay = 417;
378  break;
379  case UART_RATE_38400:
380  low_br = E_AHI_UART_RATE_38400;
381  uart_char_delay = 209;
382  break;
383  case UART_RATE_76800:
384  low_br = E_AHI_UART_RATE_76800;
385  uart_char_delay = 105;
386  break;
387  case UART_RATE_115200:
388  low_br = E_AHI_UART_RATE_115200;
389  uart_char_delay = 69;
390  break;
391  case UART_RATE_230400:
392  high_br = 230400UL;
393  uart_char_delay = 35;
394  break;
395  case UART_RATE_460800:
396  high_br = 460800UL;
397  uart_char_delay = 18;
398  break;
399  case UART_RATE_500000:
400  high_br = 500000UL;
401  uart_char_delay = 16;
402  break;
403  case UART_RATE_576000:
404  high_br = 576000UL;
405  uart_char_delay = 14;
406  break;
407  case UART_RATE_921600:
408  high_br = 921600UL;
409  uart_char_delay = 9;
410  break;
411  case UART_RATE_1000000:
412  high_br = 1000000UL;
413  uart_char_delay = 8;
414  break;
415  default:
416  high_br = 1000000UL;
417  uart_char_delay = 8;
418  break;
419  }
420  if(high_br == 0) {
421  vAHI_UartSetClockDivisor(uart_dev, low_br);
422  } else {
423  uart_driver_set_high_baudrate(uart_dev, high_br);
424  }
425 }
426 /****************************************************************************
427  *
428  * NAME: uart_driver_set_high_baudrate
429  *
430  * DESCRIPTION:
431  * Sets the baud rate for the specified uart
432  *
433  * PARAMETERS: Name RW Usage
434  * uart_dev R UART to initialise, eg, E_AHI_UART_0
435  * baud_rate R Baudrate to use (bps eg 921600)
436  *
437  * RETURNS:
438  * void
439  *
440  ****************************************************************************/
441 static void
442 uart_driver_set_high_baudrate(uint8_t uart_dev, uint32_t baud_rate)
443 {
444  uint16 u16Divisor = 1;
445  uint32_t u32Remainder;
446  uint8_t u8ClocksPerBit = 16;
447 
448 #if (ENABLE_ADVANCED_BAUD_SELECTION)
449  /* Defining ENABLE_ADVANCED_BAUD_SELECTION in the Makefile
450  * enables this code which searches for a clocks per bit setting
451  * that gets closest to the configured rate.
452  */
453  uint32_t u32CalcBaudRate = 0;
454  int32 i32BaudError = 0x7FFFFFFF;
455 
456  DBG_vPrintf(DEBUG_UART_BUFFERED, "Config uart=%d, baud=%d\n", uart_dev,
457  baud_rate);
458 
459  while(ABS(i32BaudError) > (int32)(baud_rate >> 4)) { /* 6.25% (100/16) error */
460  if(--u8ClocksPerBit < 3) {
461  DBG_vPrintf(DEBUG_UART_BUFFERED,
462  "Could not calculate UART settings for target baud!");
463  return;
464  }
465 #endif /* ENABLE_ADVANCED_BAUD_SELECTION */
466 
467  /* Calculate Divisor register = 16MHz / (16 x baud rate) */
468  u16Divisor = (uint16)(16000000UL / ((u8ClocksPerBit + 1) * baud_rate));
469 
470  /* Correct for rounding errors */
471  u32Remainder =
472  (uint32_t)(16000000UL % ((u8ClocksPerBit + 1) * baud_rate));
473 
474  if(u32Remainder >= (((u8ClocksPerBit + 1) * baud_rate) / 2)) {
475  u16Divisor += 1;
476  }
477 #if (ENABLE_ADVANCED_BAUD_SELECTION)
478  DBG_vPrintf(DEBUG_UART_BUFFERED, "Divisor=%d, cpb=%d\n", u16Divisor,
479  u8ClocksPerBit);
480 
481  u32CalcBaudRate = (16000000UL / ((u8ClocksPerBit + 1) * u16Divisor));
482 
483  DBG_vPrintf(DEBUG_UART_BUFFERED, "Calculated baud=%d\n", u32CalcBaudRate);
484 
485  i32BaudError = (int32)u32CalcBaudRate - (int32)baud_rate;
486 
487  DBG_vPrintf(DEBUG_UART_BUFFERED, "Error baud=%d\n", i32BaudError);
488 }
489 DBG_vPrintf(DEBUG_UART_BUFFERED, "Config uart=%d: Divisor=%d, cpb=%d\n",
490  uart_dev, u16Divisor, u8ClocksPerBit);
491 
492 /* Set the calculated clocks per bit */
493 vAHI_UartSetClocksPerBit(uart_dev, u8ClocksPerBit);
494 #endif /* ENABLE_ADVANCED_BAUD_SELECTION */
495 
496  /* Set the calculated divisor */
497  vAHI_UartSetBaudDivisor(uart_dev, u16Divisor);
498 }
499 
500 /****************************************************************************
501  *
502  * NAME: uart_driver_isr
503  *
504  * DESCRIPTION:
505  * Interrupt service callback for UART's
506  *
507  * PARAMETERS: Name RW Usage
508  * device_id R Device ID of whatever generated the
509  * interrupt
510  * item_bitmap R Which part of the device generated
511  * the interrupt
512  *
513  * RETURNS:
514  * void
515  *
516  ****************************************************************************/
517 static void
518 uart_driver_isr(uint32_t device_id, uint32_t item_bitmap)
519 {
520  uint8_t uart_dev;
521  switch(device_id) {
522  case E_AHI_DEVICE_UART0:
523  uart_dev = E_AHI_UART_0;
524  break;
525  case E_AHI_DEVICE_UART1:
526  uart_dev = E_AHI_UART_1;
527  break;
528  default:
529  return;
530  }
531  switch(item_bitmap) {
532  /* byte available since a long time but RX-fifo not full: */
533  case E_AHI_UART_INT_TIMEOUT:
534  /* RX-fifo full: */
535  case E_AHI_UART_INT_RXDATA:
536  uart_driver_rx_handler(uart_dev);
537  break;
538  case E_AHI_UART_INT_TX:
539  break;
540  case E_AHI_UART_INT_RXLINE:
541  /* rx-line interrupt is disabled. Should not get here */
542  /* An error condition has occurred on the RxD line, such as
543  a break indication, framing error, parity error or over-run. */
544  break;
545  }
546 }
547 /****************************************************************************
548  *
549  * NAME: uart_driver_tx_in_progress
550  *
551  * DESCRIPTION:
552  * Returns the state of data transmission
553  *
554  * PARAMETERS: Name RW Usage
555  * uart_dev R UART to use, eg, E_AHI_UART_0
556  *
557  * RETURNS:
558  * uint8_t: TRUE if data in buffer is being transmitted
559  * FALSE if all data in buffer has been transmitted by the UART
560  *
561  ****************************************************************************/
562 uint8_t
563 uart_driver_tx_in_progress(uint8_t uart_dev)
564 {
565 
566  if(u16AHI_UartReadTxFifoLevel(uart_dev) == 0) {
567  if((u8AHI_UartReadLineStatus(uart_dev) & E_AHI_UART_LS_TEMT) != 0) {
568  return FALSE;
569  }
570  }
571  return TRUE;
572 }
573 #ifdef UART_EXTRAS
574 
575 /****************************************************************************
576  *
577  * NAME: uart_driver_flush
578  *
579  * DESCRIPTION:
580  * Flushes the buffers of the specified UART
581  *
582  * PARAMETERS: Name RW Usage
583  * uart_dev R UART to disable, eg, E_AHI_UART_0
584  * reset_tx R to reset the transmit FIFO
585  * reset_rx R to reset the receive FIFO
586  *
587  * RETURNS:
588  * void
589  *
590  ****************************************************************************/
591 void
592 uart_driver_flush(uint8_t uart_dev, bool_t reset_tx, bool_t reset_rx)
593 {
594  /* Disable TX Fifo empty and Rx data interrupts */
595  uart_driver_disable_interrupts(uart_dev);
596 
597  /* flush hardware buffer */
598  vAHI_UartReset(uart_dev, reset_tx, reset_rx);
599  vAHI_UartReset(uart_dev, FALSE, FALSE);
600 
601  /* Re-enable TX Fifo empty and Rx data interrupts */
602  uart_driver_enable_interrupts(uart_dev);
603 }
604 #endif /* UART_EXTRAS */
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
Header file for the dbg-io module.
Header file for the real-time timer module.
Header file for the Contiki process interface.
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85