HWA
Bare metal programming with style
wdb_2.h
Go to the documentation of this file.
1 
2 /* This file is part of the HWA project.
3  * Copyright (c) 2012,2015 Christophe Duparquet.
4  * All rights reserved. Read LICENSE.TXT for details.
5  */
6 
43 #define hwa_configure__wdb , _hwa_cfwdb
44 
45 /* Optionnal argument `timeout`
46  */
47 #define _hw_wdb_timeout_16ms , 0
48 #define _hw_wdb_timeout_32ms , 1
49 #define _hw_wdb_timeout_64ms , 2
50 #define _hw_wdb_timeout_125ms , 3
51 #define _hw_wdb_timeout_250ms , 4
52 #define _hw_wdb_timeout_500ms , 5
53 #define _hw_wdb_timeout_1s , 6
54 #define _hw_wdb_timeout_2s , 7
55 #define _hw_wdb_timeout_4s , 8
56 #define _hw_wdb_timeout_8s , 9
57 
58 #define _hwa_cfwdb(o,a,k,...) \
59  do { HW_B(_hwa_cfwdb_ktimeout_,_hw_is_timeout_##k)(o,k,__VA_ARGS__,,) }while(0)
60 
61 #define _hwa_cfwdb_ktimeout_1(o,k,v,...) \
62  HW_B(_hwa_cfwdb_vtimeout_,_hw_wdb_timeout_##v)(o,v,__VA_ARGS__)
63 
64 #define _hwa_cfwdb_vtimeout_0(o,v,...) \
65  HW_E(HW_EM_VAL(v,timeout,(16ms,32ms,64ms,125ms,250ms,500ms,1s,2s,4s,8s)))
66 
67 #define _hwa_cfwdb_vtimeout_1(o,v,k,...) \
68  hwa->o.config.timeout = HW_A1(_hw_wdb_timeout_##v); \
69  HW_B(_hwa_cfwdb_kaction_,_hw_is_action_##k)(o,k,__VA_ARGS__)
70 
71 #define _hwa_cfwdb_ktimeout_0(...) \
72  HW_B(_hwa_cfwdb_kaction_,_hw_is_action_##k)(o,k,__VA_ARGS__)
73 
74 /* Mandatory argument `action`
75  */
76 #define _hw_wdb_action_none , 0
77 #define _hw_wdb_action_irq , 1
78 #define _hw_wdb_action_reset , 2
79 #define _hw_wdb_action_irq_or_reset , 3
80 
81 #define _hwa_cfwdb_kaction_0(o,k,...) HW_E(HW_EM_VL(k,(action)))
82 #define _hwa_cfwdb_kaction_1(o,k,v,...) HW_B(_hwa_cfwdb_vaction_,_hw_wdb_action_##v)(o,v,__VA_ARGS__)
83 #define _hwa_cfwdb_vaction_0(o,v,...) HW_E(HW_EM_VAL(v,action,(none,irq,reset,irq_or_reset)))
84 #define _hwa_cfwdb_vaction_1(o,v,...) \
85  hwa->o.config.action = HW_A1(_hw_wdb_action_##v); \
86  HW_EOL(__VA_ARGS__)
87 
88 
112 #define hw_enable__wdb , _hw_enwdb
113 #define _hw_enwdb(o,a) _hw_write(o,wde,1)
114 
115 #define hwa_enable__wdb , _hwa_enwdb
116 #define _hwa_enwdb(o,a) _hwa_write(o,wde,1)
117 
118 #define hw_disable__wdb , _hw_dswdb
119 #define hwa_disable__wdb , _hwa_dswdb
120 
121 /* Disable the watchdog by clearing WDE. That special sequence must be
122  * respected.
123  *
124  * FIXME: that also clears WDRF (required) and other reset flags, as well
125  * as WDIE but this should not be a problem. WDP and WDIF are left intact.
126  * May be should only clear WDRF
127  *
128  * FIXME: 0x27 is the mask for WDP bits in WDTCR
129  */
130 #define _hw_dswdb(o,...) \
131  do { \
132  uint8_t reg ; \
133  _hw_write( core0, mcusr, 0 ); \
134  __asm__ __volatile__(" in %[r], %[wdtcr]" "\n\t" \
135  " ori %[r], %[wdce]|%[wde]" "\n\t" \
136  " out %[wdtcr], %[r]" "\n\t" \
137  " andi %[r], %[wdp]" "\n\t" \
138  " out %[wdtcr], %[r]" "\n\t" \
139  : [r] "=&d" (reg) \
140  : [wdtcr] "I" (HW_ADDRESS((o, csr))-0x20), \
141  [wdce] "I" (1<<HW_POSITION((o, wdce))), \
142  [wde] "I" (1<<HW_POSITION((o, wde))), \
143  [wdp] "I" (0x27)); \
144  } while(0)
145 
146 
147 /* Action completed when committing
148  */
149 #define _hwa_dswdb(o,...) hwa->o.config.action = HW_A1(_hw_wdb_action_none)
150 
151 
161 #define hw_reset__wdb , _hw_rstwdb
162 
163 #define _hw_rstwdb(o,a,...) hw_asm("wdr"::) HW_EOL(__VA_ARGS__)
164 
165 
166 /*******************************************************************************
167  * *
168  * Context management *
169  * *
170  *******************************************************************************/
171 
172 #define _hwa_setup__wdb(o,a) \
173  _hwa_setup_r( o, csr ); \
174  hwa->o.config.action = 0xFF ; \
175  hwa->o.config.timeout = 0xFF
176 
177 #define _hwa_init__wdb(o,a) _hwa_init_r( o, csr, 0x00 )
178 
179 /* Commit the configuration of a _wdb class watchdog
180  *
181  * Turning the watchdog off requires to:
182  * 1. Clear WDRF
183  * 2. Clear WDIF
184  * 3. Set WDCE and WDE to 1 in the same operation
185  * 4. Set WDE to 0 within 4 cycles after step 3.
186  */
187 #define _hwa_commit__wdb(o,a) \
188  do { \
189  if ( hwa->o.config.action != 0xFF ) { \
190  if ( hwa->o.config.action == HW_A1(_hw_wdb_action_none) ) { \
191  /* Turn it off */ \
192  if ( HW_DEVICE_FUSE_WDTON == 0 ) \
193  HWA_E(HW_EM_4); \
194  _hwa_write( o, wdrf, 0 ); \
195  _hwa_commit_r( o, wdrf ); \
196  _hwa_write( o, if, 1 ); /* was not in _wodga */ \
197  _hwa_write( o, wdce, 1 ); \
198  _hwa_write( o, wde, 1 ); \
199  _hwa_commit_r( o, csr ); \
200  _hwa_write( o, ie, 0 ); \
201  _hwa_write( o, wdce, 0 ); \
202  _hwa_write( o, wde, 0 ); \
203  _hwa_write( o, wdp, 0 ); \
204  } \
205  else { \
206  /* Configure it */ \
207  _hwa_write( o, wdce, 1 ); /* was not in _wodga */ \
208  _hwa_write( o, wde, 1 ); /* was not in _wodga */ \
209  _hwa_commit_r( o, csr ); /* was not in _wodga */ \
210  _hwa_write( o, wdce, 0 ); /* was not in _wodga */ \
211  _hwa_write( o, eie, hwa->o.config.action ); \
212  if ( hwa->o.config.timeout != 0xFF ) \
213  _hwa_write( o, wdp, hwa->o.config.timeout ); \
214  } \
215  /* hwa->o.config.action = 0xFF ; */ \
216  /* hwa->o.config.timeout = 0xFF ; */ \
217  } \
218  _hwa_commit_r( o, csr ); \
219  } while(0)