Contiki 3.x
init.c
1 #include <stdio.h>
2 
3 /* debug */
4 #define DEBUG DEBUG_FULL
5 #include "net/ip/uip-debug.h"
6 
7 /* contiki */
8 #include "sys/process.h"
9 
10 /* mc1322x */
11 #include "mc1322x.h"
12 #include "contiki-maca.h"
13 #include "config.h"
14 
15 /* Threshold for buck converter; buck will be disabled if vbatt is below this */
16 #define MC1322X_BUCK_THRES 2425
17 /* Hysterisis window around buck threshold */
18 #define MC1322X_BUCK_WINDOW 150
19 #define MC1322X_BUCK_THRES_H (MC1322X_BUCK_THRES + MC1322X_BUCK_WINDOW/2)
20 #define MC1322X_BUCK_THRES_L (MC1322X_BUCK_THRES - MC1322X_BUCK_WINDOW/2)
21 /* Time between vbatt checks for the buck */
22 #define MC1322X_BUCK_MONITOR_PERIOD 600 * CLOCK_SECOND
23 
24 /* periodically poll adc_vbatt and manages the buck appropriately */
25 static struct etimer et_buck;
26 PROCESS(buck_monitor, "buck monitor");
27 PROCESS_THREAD(buck_monitor, ev, data)
28 {
29 
30  PROCESS_BEGIN();
31  PRINTF("starting vbatt monitor\n");
32 
33  etimer_set(&et_buck, MC1322X_BUCK_MONITOR_PERIOD);
34 
35  while (1) {
37  if(etimer_expired(&et_buck))
38  {
39  adc_service();
40  PRINTF("buck monitor: vbatt: %d mV\n\r", adc_vbatt);
41  if( CRM->VREG_CNTLbits.BUCK_EN == 1 && adc_vbatt < MC1322X_BUCK_THRES_L ) {
42  PRINTF("vbatt low, disabling buck\n\r", adc_vbatt);
43  CRM->SYS_CNTLbits.PWR_SOURCE = 0;
44  CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 0;
45  CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 1;
46  CRM->VREG_CNTLbits.BUCK_EN = 0;
47  } else if ( CRM->VREG_CNTLbits.BUCK_EN == 0 && adc_vbatt > MC1322X_BUCK_THRES_H ) {
48  PRINTF("vbatt high, enabling buck\n\r", adc_vbatt);
49  CRM->SYS_CNTLbits.PWR_SOURCE = 1;
50  CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 1;
51  CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 0;
52  CRM->VREG_CNTLbits.BUCK_EN = 1;
53  }
54  etimer_set(&et_buck, MC1322X_BUCK_MONITOR_PERIOD);
55  }
56  }
57 
58  PROCESS_END();
59 
60 }
61 
62 void buck_setup(void) {
63  nvmType_t type;
64  nvmErr_t err;
65  volatile int i;
66 
67  default_vreg_init();
68 
69  while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; }
70  while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; }
71 
72  /* takes time for the flash supply to fail (if there is no buck) */
73  /* spin while this happens doing nvm_detects */
74  /* XXX todo: don't probe buck if Vbatt < 2.5V */
75 
76  adc_service();
77  PRINTF("vbatt: %04u mV\n\r", adc_vbatt);
78 
79  type = 1;
80  for(i = 0; i < 128 && type != 0; i++) {
81  err = nvm_detect(gNvmInternalInterface_c, &type);
82  }
83  if (type == gNvmType_NoNvm_c)
84  {
85  PRINTF("NVM failed without buck, trying with buck\n\r");
86 
87  if (adc_vbatt < MC1322X_BUCK_THRES_L)
88  {
89  PRINTF("Vbatt is low, bypassing buck\n\r");
90  CRM->SYS_CNTLbits.PWR_SOURCE = 0;
91  CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 0;
92  CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 1;
93  CRM->VREG_CNTLbits.BUCK_EN = 0;
94  } else {
95  CRM->SYS_CNTLbits.PWR_SOURCE = 1;
96  CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 1;
97  CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 0;
98  CRM->VREG_CNTLbits.BUCK_EN = 1;
99  }
100 
101  while(CRM->STATUSbits.VREG_BUCK_RDY == 0) { continue; }
102  CRM->VREG_CNTLbits.VREG_1P5V_SEL = 3;
103  CRM->VREG_CNTLbits.VREG_1P5V_EN = 3;
104  CRM->VREG_CNTLbits.VREG_1P8V_EN = 1;
105 
106  while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; }
107  while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; }
108 
109  type = 1;
110  for(i = 0; i < 128 && type != 0; i++) {
111  err = nvm_detect(gNvmInternalInterface_c, &type);
112  }
113  if (type != gNvmType_NoNvm_c) {
114  PRINTF("buck ok\n\r");
115  /* start a process to monitor vbatt and enable/disable the buck as necessary */
116  process_start(&buck_monitor, NULL);
117  } else {
118  printf("fatal: couldn't detect NVM\n\r");
119  }
120  } else {
121  PRINTF("NVM ok without buck\n\r");
122  }
123 }
124 
125 /* setup the RTC */
126 /* try to start the 32kHz xtal */
127 void rtc_setup(void) {
128  volatile uint32_t rtc_count;
129  volatile uint32_t i;
130 
131  ring_osc_off();
132  xtal32_on();
133  xtal32_exists();
134  rtc_count = CRM->RTC_COUNT;
135  PRINTF("trying to start 32kHz xtal\n\r");
136 
137  for(i = 0; i < 150000 && CRM->RTC_COUNT == rtc_count; i++) { continue; }
138  if(CRM->RTC_COUNT == rtc_count) {
139  PRINTF("32xtal failed, using ring osc\n\r");
140  CRM->SYS_CNTLbits.XTAL32_EXISTS = 0;
141  CRM->XTAL32_CNTLbits.XTAL32_EN = 0;
142  ring_osc_on();
143 
144  /* Set default tune values from datasheet */
145  CRM->RINGOSC_CNTLbits.ROSC_CTUNE = 0x6;
146  CRM->RINGOSC_CNTLbits.ROSC_FTUNE = 0x17;
147 
148  /* Trigger calibration */
149  rtc_calibrate();
150  PRINTF("RTC calibrated to %d Hz\r\n", rtc_freq);
151  } else {
152  PRINTF("32kHz xtal started\n\r");
153  rtc_freq = 32768;
154  }
155 }
156 
157 /* call mc1322x_init once to initalize everything with the current config */
158 void mc1322x_init(void) {
159 
160  /* XXX TODO load config from flash */
161  /* config should say what uart to use for debug console */
162  /* config should also set the baud rate */
163  /* for now, just clean up contiki-conf.h */
164  /* maybe factor into conf.h -> contiki-conf.h and mc1322x-conf.h platform-conf.h */
165 
166  /* print out config in debug */
167  /* initialize the uarts */
168  uart_init(CONSOLE_UART, CONSOLE_BAUD);
169  PRINTF("mc1322x init\n\r");
170 
171  adc_init();
172  ctimer_init();
173  process_init();
174  process_start(&etimer_process, NULL);
175  process_start(&contiki_maca_process, NULL);
176  buck_setup();
177 
178  /* start with a default config */
179 
180  mc1322x_config_restore(&mc1322x_config);
181  if ( mc1322x_config_valid(&mc1322x_config) != 1 ) {
182  PRINTF("flash invalid\n\r");
183  /* save the default config to flash */
184  mc1322x_config_set_default(&mc1322x_config);
185  mc1322x_config_save(&mc1322x_config);
186  }
187 
188 #if DEBUG_FULL
189  mc1322x_config_print();
190 #endif
191 
192  /* setup the radio */
193  maca_init();
194  set_power(mc1322x_config.power);
195  set_channel(mc1322x_config.channel);
196  set_demodulator_type(mc1322x_config.flags.demod);
197  set_prm_mode(mc1322x_config.flags.autoack);
198 
199  /* must be done AFTER maca_init */
200  /* the radio calibration appears to clobber the RTC trim caps */
201  rtc_setup();
202  rtimer_init();
203  clock_init();
204 
205 }
206 
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:205
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
void rtimer_init(void)
Initialize the real-time scheduler.
Definition: rtimer.c:61
void uart_init(const unsigned int uart_num, uint32_t module_clk_hz, const uint32_t baud)
Initialize UART.
Definition: uart.c:154
#define NULL
The null pointer.
void clock_init(void)
Initialize the clock library.
Definition: clock.c:76
void process_init(void)
Initialize the process module.
Definition: process.c:208
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
void ctimer_init(void)
Initialize the callback timer library.
Definition: ctimer.c:91
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
A set of debugging macros.
void adc_init(void)
Initializes the ADC controller.
Definition: adc.c:50
Header file for the Contiki process interface.
A timer.
Definition: etimer.h:76