HWA
Bare metal programming with style
wda_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__wda , _hwa_cfwda
44 
45 /* Optionnal argument `timeout`
46  */
47 #define _hw_wda_timeout_16ms , 0
48 #define _hw_wda_timeout_32ms , 1
49 #define _hw_wda_timeout_64ms , 2
50 #define _hw_wda_timeout_125ms , 3
51 #define _hw_wda_timeout_250ms , 4
52 #define _hw_wda_timeout_500ms , 5
53 #define _hw_wda_timeout_1s , 6
54 #define _hw_wda_timeout_2s , 7
55 #define _hw_wda_timeout_4s , 8
56 #define _hw_wda_timeout_8s , 9
57 
58 #define _hwa_cfwda(o,a,k,...) \
59  do { HW_B(_hwa_cfwda_ktimeout_,_hw_is_timeout_##k)(o,k,__VA_ARGS__,,) }while(0)
60 
61 #define _hwa_cfwda_ktimeout_1(o,k,v,...) \
62  HW_B(_hwa_cfwda_vtimeout_,_hw_wda_timeout_##v)(o,v,__VA_ARGS__)
63 
64 #define _hwa_cfwda_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_cfwda_vtimeout_1(o,v,k,...) \
68  hwa->o.config.timeout = HW_A1(_hw_wda_timeout_##v); \
69  HW_B(_hwa_cfwda_kaction_,_hw_is_action_##k)(o,k,__VA_ARGS__)
70 
71 #define _hwa_cfwda_ktimeout_0(...) \
72  HW_B(_hwa_cfwda_kaction_,_hw_is_action_##k)(o,k,__VA_ARGS__)
73 
74 /* Mandatory argument `action`
75  */
76 #define _hw_wda_action_none , 0
77 #define _hw_wda_action_irq , 1
78 #define _hw_wda_action_reset , 2
79 #define _hw_wda_action_irq_or_reset , 3
80 
81 #define _hwa_cfwda_kaction_0(o,k,...) \
82  HW_E(HW_EM_AN(k,action))
83 
84 #define _hwa_cfwda_kaction_1(o,k,v,...) \
85  HW_B(_hwa_cfwda_vaction_,_hw_wda_action_##v)(o,v,__VA_ARGS__)
86 
87 #define _hwa_cfwda_vaction_0(o,v,...) \
88  HW_E(HW_EM_VAL(v,action,(none,irq,reset,irq_or_reset)))
89 
90 #define _hwa_cfwda_vaction_1(o,v,...) \
91  hwa->o.config.action = HW_A1(_hw_wda_action_##v); \
92  HW_EOL(__VA_ARGS__)
93 
94 
118 #define hw_enable__wda , _hw_enwda
119 #define _hw_enwda(o,a) _hw_write(o,wde,1)
120 
121 #define hwa_enable__wda , _hwa_enwda
122 #define _hwa_enwda(o,a) _hwa_write(o,wde,1)
123 
124 #define hw_disable__wda , _hw_dswda
125 #define hwa_disable__wda , _hwa_dswda
126 
127 
128 /* Disable the watchdog by clearing WDE. That special sequence must be
129  * respected.
130  *
131  * FIXME: that also clears WDRF (required) and other reset flags, as well
132  * as WDIE but this should not be a problem. WDP and WDIF are left intact.
133  * May be should only clear WDRF
134  *
135  * FIXME: 0x27 is the mask for WDP bits in WDTCR
136  */
137 #define _hw_dswda(o,...) \
138  do { \
139  uint8_t reg ; \
140  _hw_write( core0, mcusr, 0 ); \
141  __asm__ __volatile__(" in %[r], %[wdtcr]" "\n\t" \
142  " ori %[r], %[wdce]|%[wde]" "\n\t" \
143  " out %[wdtcr], %[r]" "\n\t" \
144  " andi %[r], %[wdp]" "\n\t" \
145  " out %[wdtcr], %[r]" "\n\t" \
146  : [r] "=&d" (reg) \
147  : [wdtcr] "I" (HW_ADDRESS((o, csr))-0x20), \
148  [wdce] "I" (1<<HW_POSITION((o, wdce))), \
149  [wde] "I" (1<<HW_POSITION((o, wde))), \
150  [wdp] "I" (0x27)); \
151  } while(0)
152 
153 
154 /* Action completed when committing
155  */
156 #define _hwa_dswda(o,...) hwa->o.config.action = HW_A1(_hw_wda_action_none)
157 
158 
159 
169 #define hw_reset__wda , _hw_rstwda
170 
171 #define _hw_rstwda(...) hw_asm("wdr"::) HW_EOL(__VA_ARGS__)
172 
173 
174 /*******************************************************************************
175  * *
176  * Context management *
177  * *
178  *******************************************************************************/
179 
180 #define _hwa_setup__wda(o,a) \
181  _hwa_setup_r( o, csr ); \
182  hwa->o.config.action = 0xFF ; \
183  hwa->o.config.timeout = 0xFF
184 
185 
186 #define _hwa_init__wda(o,a) _hwa_init_r( o, csr, 0x00 )
187 
188 
189 /* Commit the configuration of a _wda class watchdog
190  *
191  * Turning the watchdog off requires:
192  * 1. Clearing WDRF
193  * 2. Setting WDCE and WDE to 1 in the same operation
194  * 3. Setting WDE to 0 within 4 cycles after 2.
195  */
196 #define _hwa_commit__wda(o,a) \
197  do { \
198  if ( hwa->o.config.action != 0xFF ) { \
199  if ( hwa->o.config.action == HW_A1(_hw_wda_action_none) ) { \
200  /* Turn it off */ \
201  if ( HW_DEVICE_WDTON == 0 ) \
202  HWA_E(HW_EM_4); \
203  _hwa_write( o, wdrf, 0 ); \
204  _hwa_commit_r( o, wdrf ); \
205  _hwa_write( o, wdce, 1 ); \
206  _hwa_write( o, wde, 1 ); \
207  _hwa_commit_r( o, csr ); \
208  _hwa_write( o, ie, 0 ); \
209  _hwa_write( o, wdce, 0 ); \
210  _hwa_write( o, wde, 0 ); \
211  _hwa_write( o, wdp, 0 ); \
212  } \
213  else { \
214  /* Configure it */ \
215  _hwa_write( o, eie, hwa->o.config.action ); \
216  if ( hwa->o.config.timeout != 0xFF ) \
217  _hwa_write( o, wdp, hwa->o.config.timeout ); \
218  } \
219  hwa->o.config.action = 0xFF ; \
220  hwa->o.config.timeout = 0xFF ; \
221  } \
222  _hwa_commit_r( o, csr ); \
223  } while(0)