FreeCalypso > hg > fc-tourmaline
comparison src/cs/drivers/drv_core/abb/abb.c @ 220:0ed36de51973
ABB semaphore protection overhaul
The ABB semaphone protection logic that came with TCS211 from TI
was broken in several ways:
* Some semaphore-protected functions were called from Application_Initialize()
context. NU_Obtain_Semaphore() called with NU_SUSPEND fails with
NU_INVALID_SUSPEND in this context, but the return value wasn't checked,
and NU_Release_Semaphore() would be called unconditionally at the end.
The latter call would increment the semaphore count past 1, making the
semaphore no longer binary and thus no longer effective for resource
protection. The fix is to check the return value from NU_Obtain_Semaphore()
and skip the NU_Release_Semaphore() call if the semaphore wasn't properly
obtained.
* Some SPI hardware manipulation was being done before entering the semaphore-
protected critical section. The fix is to reorder the code: first obtain
the semaphore, then do everything else.
* In the corner case of L1/DSP recovery, l1_abb_power_on() would call some
non-semaphore-protected ABB & SPI init functions. The fix is to skip those
calls in the case of recovery.
* A few additional corner cases existed, all of which are fixed by making
ABB semaphore protection 100% consistent for all ABB functions and code paths.
There is still one remaining problem of priority inversion: suppose a low-
priority task calls an ABB function, and some medium-priority task just happens
to preempt right in the middle of that semaphore-protected ABB operation. Then
the high-priority SPI task is locked out for a non-deterministic time until
that medium-priority task finishes its work and goes back to sleep. This
priority inversion problem remains outstanding for now.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 26 Apr 2021 20:55:25 +0000 |
parents | d00662aa64d8 |
children | 160a5b3a076c |
comparison
equal
deleted
inserted
replaced
219:d00662aa64d8 | 220:0ed36de51973 |
---|---|
140 /* This function waits for the first IBIC access. */ | 140 /* This function waits for the first IBIC access. */ |
141 /* */ | 141 /* */ |
142 /*-----------------------------------------------------------------------*/ | 142 /*-----------------------------------------------------------------------*/ |
143 void ABB_Wait_IBIC_Access(void) | 143 void ABB_Wait_IBIC_Access(void) |
144 { | 144 { |
145 #if (ANLG_FAM ==1) | 145 #if (ANLG_FAM == 1) |
146 // Wait 6 OSCAS cycles (100 KHz) for first IBIC access | 146 // Wait 6 OSCAS cycles (100 KHz) for first IBIC access |
147 // (i.e wait 60us + 10% security marge = 66us) | 147 // (i.e wait 60us + 10% security marge = 66us) |
148 wait_ARM_cycles(convert_nanosec_to_cycles(66000)); | 148 wait_ARM_cycles(convert_nanosec_to_cycles(66000)); |
149 #elif ((ANLG_FAM ==2) || (ANLG_FAM == 3)) | 149 #elif ((ANLG_FAM == 2) || (ANLG_FAM == 3)) |
150 // Wait 6 x 32 KHz clock cycles for first IBIC access | 150 // Wait 6 x 32 KHz clock cycles for first IBIC access |
151 // (i.e wait 187us + 10% security marge = 210us) | 151 // (i.e wait 187us + 10% security marge = 210us) |
152 wait_ARM_cycles(convert_nanosec_to_cycles(210000)); | 152 wait_ARM_cycles(convert_nanosec_to_cycles(210000)); |
153 #endif | 153 #endif |
154 } | 154 } |
155 | 155 |
156 | 156 |
157 | |
158 /*-----------------------------------------------------------------------*/ | 157 /*-----------------------------------------------------------------------*/ |
159 /* ABB_Write_Register_on_page() */ | 158 /* ABB_Write_Register_on_page() */ |
160 /* */ | 159 /* */ |
161 /* This function manages all the spi serial transfer to write to an */ | 160 /* This function manages all the spi serial transfer to write to an */ |
162 /* ABB register on a specified page. */ | 161 /* ABB register on a specified page. */ |
163 /* */ | 162 /* */ |
164 /*-----------------------------------------------------------------------*/ | 163 /*-----------------------------------------------------------------------*/ |
165 void ABB_Write_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id, SYS_UWORD16 value) | 164 void ABB_Write_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id, SYS_UWORD16 value) |
166 { | 165 { |
167 volatile SYS_UWORD16 status; | 166 volatile SYS_UWORD16 status; |
167 STATUS sem_status; | |
168 | |
169 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
170 | |
171 // check if the semaphore has been correctly created and try to obtain it. | |
172 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
173 // as soon as the semaphore is released. | |
174 | |
175 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
176 | |
177 #endif // ABB_SEMAPHORE_PROTECTION | |
168 | 178 |
169 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | 179 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. |
170 SPI_Ready_for_WR | 180 SPI_Ready_for_WR |
171 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | 181 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
172 | 182 |
183 // set the ABB page for register access | |
184 ABB_SetPage(page); | |
185 | |
186 // Write value in reg_id | |
187 ABB_WriteRegister(reg_id, value); | |
188 | |
189 // set the ABB page for register access at page 0 | |
190 ABB_SetPage(PAGE0); | |
191 | |
192 // Stop the SPI clock | |
193 #ifdef SPI_CLK_LOW_POWER | |
194 SPI_CLK_DISABLE | |
195 #endif | |
196 | |
197 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
198 // release the semaphore only if it has correctly been created. | |
199 if(sem_status == NU_SUCCESS) | |
200 { | |
201 NU_Release_Semaphore(&abb_sem); | |
202 } | |
203 #endif // ABB_SEMAPHORE_PROTECTION | |
204 } | |
205 | |
206 | |
207 /*-----------------------------------------------------------------------*/ | |
208 /* ABB_Read_Register_on_page() */ | |
209 /* */ | |
210 /* This function manages all the spi serial transfer to read one */ | |
211 /* ABB register on a specified page. */ | |
212 /* */ | |
213 /* Returns the real data value of the register. */ | |
214 /* */ | |
215 /*-----------------------------------------------------------------------*/ | |
216 SYS_UWORD16 ABB_Read_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id) | |
217 { | |
218 volatile SYS_UWORD16 status; | |
219 STATUS sem_status; | |
220 SYS_UWORD16 reg_val; | |
221 | |
173 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | 222 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) |
174 | 223 |
175 // check if the semaphore has been correctly created and try to obtain it. | 224 // check if the semaphore has been correctly created and try to obtain it. |
176 // if the semaphore cannot be obtained, the task is suspended and then resumed | 225 // if the semaphore cannot be obtained, the task is suspended and then resumed |
177 // as soon as the semaphore is released. | 226 // as soon as the semaphore is released. |
178 if(&abb_sem != 0) | 227 |
179 { | 228 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); |
180 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | 229 |
181 } | 230 #endif // ABB_SEMAPHORE_PROTECTION |
182 #endif // ABB_SEMAPHORE_PROTECTION | 231 |
183 | 232 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. |
184 // set the ABB page for register access | 233 SPI_Ready_for_RDWR |
234 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
235 | |
236 /* set the ABB page for register access */ | |
185 ABB_SetPage(page); | 237 ABB_SetPage(page); |
186 | 238 |
187 // Write value in reg_id | 239 /* Read selected ABB register */ |
188 ABB_WriteRegister(reg_id, value); | 240 reg_val = ABB_ReadRegister(reg_id); |
189 | 241 |
190 // set the ABB page for register access at page 0 | 242 /* set the ABB page for register access at page 0 */ |
191 ABB_SetPage(PAGE0); | 243 ABB_SetPage(PAGE0); |
192 | |
193 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
194 // release the semaphore only if it has correctly been created. | |
195 if(&abb_sem != 0) | |
196 { | |
197 NU_Release_Semaphore(&abb_sem); | |
198 } | |
199 #endif // ABB_SEMAPHORE_PROTECTION | |
200 | 244 |
201 // Stop the SPI clock | 245 // Stop the SPI clock |
202 #ifdef SPI_CLK_LOW_POWER | 246 #ifdef SPI_CLK_LOW_POWER |
203 SPI_CLK_DISABLE | 247 SPI_CLK_DISABLE |
204 #endif | 248 #endif |
205 } | 249 |
206 | 250 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) |
207 | 251 // release the semaphore only if it has correctly been created. |
208 /*-----------------------------------------------------------------------*/ | 252 if(sem_status == NU_SUCCESS) |
209 /* ABB_Read_Register_on_page() */ | 253 { |
210 /* */ | 254 NU_Release_Semaphore(&abb_sem); |
211 /* This function manages all the spi serial transfer to read one */ | 255 } |
212 /* ABB register on a specified page. */ | 256 #endif // ABB_SEMAPHORE_PROTECTION |
213 /* */ | 257 |
214 /* Returns the real data value of the register. */ | 258 return (reg_val); // Return result |
215 /* */ | 259 } |
216 /*-----------------------------------------------------------------------*/ | 260 |
217 SYS_UWORD16 ABB_Read_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id) | 261 /*------------------------------------------------------------------------*/ |
262 /* ABB_free_13M() */ | |
263 /* */ | |
264 /* This function sets the 13M clock working in ABB. A wait loop */ | |
265 /* is required to allow first slow access to ABB clock register. */ | |
266 /* */ | |
267 /* WARNING !! : this function must not be protected by semaphore !! */ | |
268 /* */ | |
269 /*------------------------------------------------------------------------*/ | |
270 void ABB_free_13M(void) | |
218 { | 271 { |
219 volatile SYS_UWORD16 status; | 272 volatile SYS_UWORD16 status; |
273 | |
274 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | |
275 SPI_Ready_for_WR | |
276 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
277 | |
278 ABB_SetPage(PAGE0); | |
279 | |
280 // This transmission frees the CLK13 in ABB. | |
281 ABB_WriteRegister(TOGBR2, 0x08); | |
282 | |
283 // Wait for first IBIC access | |
284 ABB_Wait_IBIC_Access(); | |
285 | |
286 // SW Workaround : This transmission has to be done twice. | |
287 ABB_WriteRegister(TOGBR2, 0x08); | |
288 | |
289 // Wait for first IBIC access | |
290 ABB_Wait_IBIC_Access(); | |
291 | |
292 // Stop the SPI clock | |
293 #ifdef SPI_CLK_LOW_POWER | |
294 SPI_CLK_DISABLE | |
295 #endif | |
296 } | |
297 | |
298 | |
299 /*------------------------------------------------------------------------*/ | |
300 /* ABB_stop_13M() */ | |
301 /* */ | |
302 /* This function stops the 13M clock in ABB. */ | |
303 /* */ | |
304 /*------------------------------------------------------------------------*/ | |
305 void ABB_stop_13M(void) | |
306 { | |
307 volatile SYS_UWORD16 status; | |
308 | |
309 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | |
310 SPI_Ready_for_WR | |
311 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
312 | |
313 ABB_SetPage(PAGE0); | |
314 | |
315 // Set ACTIVMCLK = 0. | |
316 ABB_WriteRegister(TOGBR2, 0x04); | |
317 | |
318 // Wait for first IBIC access | |
319 ABB_Wait_IBIC_Access(); | |
320 | |
321 // Stop the SPI clock | |
322 #ifdef SPI_CLK_LOW_POWER | |
323 SPI_CLK_DISABLE | |
324 #endif | |
325 } | |
326 | |
327 | |
328 /*------------------------------------------------------------------------*/ | |
329 /* ABB_Read_Status() */ | |
330 /* */ | |
331 /* This function reads and returns the value of VRPCSTS ABB register. */ | |
332 /* */ | |
333 /*------------------------------------------------------------------------*/ | |
334 SYS_UWORD16 ABB_Read_Status(void) | |
335 { | |
336 volatile SYS_UWORD16 status; | |
337 STATUS sem_status; | |
220 SYS_UWORD16 reg_val; | 338 SYS_UWORD16 reg_val; |
221 | 339 |
222 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. | 340 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) |
223 SPI_Ready_for_RDWR | |
224 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
225 | |
226 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
227 | 341 |
228 // check if the semaphore has been correctly created and try to obtain it. | 342 // check if the semaphore has been correctly created and try to obtain it. |
229 // if the semaphore cannot be obtained, the task is suspended and then resumed | 343 // if the semaphore cannot be obtained, the task is suspended and then resumed |
230 // as soon as the semaphore is released. | 344 // as soon as the semaphore is released. |
231 if(&abb_sem != 0) | 345 |
232 { | 346 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); |
233 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | 347 |
234 } | 348 #endif // ABB_SEMAPHORE_PROTECTION |
235 #endif // ABB_SEMAPHORE_PROTECTION | |
236 | |
237 /* set the ABB page for register access */ | |
238 ABB_SetPage(page); | |
239 | |
240 /* Read selected ABB register */ | |
241 reg_val = ABB_ReadRegister(reg_id); | |
242 | |
243 /* set the ABB page for register access at page 0 */ | |
244 ABB_SetPage(PAGE0); | |
245 | |
246 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
247 // release the semaphore only if it has correctly been created. | |
248 if(&abb_sem != 0) | |
249 { | |
250 NU_Release_Semaphore(&abb_sem); | |
251 } | |
252 #endif // ABB_SEMAPHORE_PROTECTION | |
253 | |
254 // Stop the SPI clock | |
255 #ifdef SPI_CLK_LOW_POWER | |
256 SPI_CLK_DISABLE | |
257 #endif | |
258 | |
259 return (reg_val); // Return result | |
260 } | |
261 | |
262 /*------------------------------------------------------------------------*/ | |
263 /* ABB_free_13M() */ | |
264 /* */ | |
265 /* This function sets the 13M clock working in ABB. A wait loop */ | |
266 /* is required to allow first slow access to ABB clock register. */ | |
267 /* */ | |
268 /* WARNING !! : this function must not be protected by semaphore !! */ | |
269 /* */ | |
270 /*------------------------------------------------------------------------*/ | |
271 void ABB_free_13M(void) | |
272 { | |
273 volatile SYS_UWORD16 status; | |
274 | 349 |
275 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | 350 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. |
276 SPI_Ready_for_WR | 351 SPI_Ready_for_WR |
277 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | 352 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
278 | |
279 ABB_SetPage(PAGE0); | |
280 | |
281 // This transmission frees the CLK13 in ABB. | |
282 ABB_WriteRegister(TOGBR2, 0x08); | |
283 | |
284 // Wait for first IBIC access | |
285 ABB_Wait_IBIC_Access(); | |
286 | |
287 // SW Workaround : This transmission has to be done twice. | |
288 ABB_WriteRegister(TOGBR2, 0x08); | |
289 | |
290 // Wait for first IBIC access | |
291 ABB_Wait_IBIC_Access(); | |
292 | |
293 // Stop the SPI clock | |
294 #ifdef SPI_CLK_LOW_POWER | |
295 SPI_CLK_DISABLE | |
296 #endif | |
297 } | |
298 | |
299 | |
300 | |
301 /*------------------------------------------------------------------------*/ | |
302 /* ABB_stop_13M() */ | |
303 /* */ | |
304 /* This function stops the 13M clock in ABB. */ | |
305 /* */ | |
306 /*------------------------------------------------------------------------*/ | |
307 void ABB_stop_13M(void) | |
308 { | |
309 volatile SYS_UWORD16 status; | |
310 | |
311 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | |
312 SPI_Ready_for_WR | |
313 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
314 | |
315 ABB_SetPage(PAGE0); | |
316 | |
317 // Set ACTIVMCLK = 0. | |
318 ABB_WriteRegister(TOGBR2, 0x04); | |
319 | |
320 // Wait for first IBIC access | |
321 ABB_Wait_IBIC_Access(); | |
322 | |
323 // Stop the SPI clock | |
324 #ifdef SPI_CLK_LOW_POWER | |
325 SPI_CLK_DISABLE | |
326 #endif | |
327 } | |
328 | |
329 | |
330 | |
331 /*------------------------------------------------------------------------*/ | |
332 /* ABB_Read_Status() */ | |
333 /* */ | |
334 /* This function reads and returns the value of VRPCSTS ABB register. */ | |
335 /* */ | |
336 /*------------------------------------------------------------------------*/ | |
337 SYS_UWORD16 ABB_Read_Status(void) | |
338 { | |
339 volatile SYS_UWORD16 status; | |
340 SYS_UWORD16 reg_val; | |
341 | |
342 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | |
343 SPI_Ready_for_WR | |
344 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
345 | |
346 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
347 | |
348 // check if the semaphore has been correctly created and try to obtain it. | |
349 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
350 // as soon as the semaphore is released. | |
351 if(&abb_sem != 0) | |
352 { | |
353 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
354 } | |
355 #endif // ABB_SEMAPHORE_PROTECTION | |
356 | 353 |
357 ABB_SetPage(PAGE0); | 354 ABB_SetPage(PAGE0); |
358 | 355 |
359 #if (ANLG_FAM == 1) || (ANLG_FAM == 2) | 356 #if (ANLG_FAM == 1) || (ANLG_FAM == 2) |
360 ABB_SetPage(PAGE0); | 357 ABB_SetPage(PAGE0); |
362 #elif (ANLG_FAM == 3) | 359 #elif (ANLG_FAM == 3) |
363 ABB_SetPage(PAGE1); | 360 ABB_SetPage(PAGE1); |
364 reg_val = ABB_ReadRegister(VRPCCFG); | 361 reg_val = ABB_ReadRegister(VRPCCFG); |
365 #endif | 362 #endif |
366 | 363 |
367 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
368 // release the semaphore only if it has correctly been created. | |
369 if(&abb_sem != 0) | |
370 { | |
371 NU_Release_Semaphore(&abb_sem); | |
372 } | |
373 #endif // ABB_SEMAPHORE_PROTECTION | |
374 | |
375 // Stop the SPI clock | 364 // Stop the SPI clock |
376 #ifdef SPI_CLK_LOW_POWER | 365 #ifdef SPI_CLK_LOW_POWER |
377 SPI_CLK_DISABLE | 366 SPI_CLK_DISABLE |
378 #endif | 367 #endif |
379 | 368 |
369 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
370 // release the semaphore only if it has correctly been created. | |
371 if(sem_status == NU_SUCCESS) | |
372 { | |
373 NU_Release_Semaphore(&abb_sem); | |
374 } | |
375 #endif // ABB_SEMAPHORE_PROTECTION | |
376 | |
380 return (reg_val); | 377 return (reg_val); |
381 } | 378 } |
382 | 379 |
383 /*------------------------------------------------------------------------*/ | 380 /*------------------------------------------------------------------------*/ |
384 /* ABB_on() */ | 381 /* ABB_on() */ |
387 /* */ | 384 /* */ |
388 /*------------------------------------------------------------------------*/ | 385 /*------------------------------------------------------------------------*/ |
389 void ABB_on(SYS_UWORD16 modules, SYS_UWORD8 bRecoveryFlag) | 386 void ABB_on(SYS_UWORD16 modules, SYS_UWORD8 bRecoveryFlag) |
390 { | 387 { |
391 volatile SYS_UWORD16 status; | 388 volatile SYS_UWORD16 status; |
392 #if ((ANLG_FAM ==2) || (ANLG_FAM == 3)) | 389 STATUS sem_status; |
390 #if ((ANLG_FAM == 2) || (ANLG_FAM == 3)) | |
393 SYS_UWORD32 reg; | 391 SYS_UWORD32 reg; |
394 #endif | 392 #endif |
393 | |
394 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
395 | |
396 // check if the semaphore has been correctly created and try to obtain it. | |
397 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
398 // as soon as the semaphore is released. | |
399 | |
400 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
401 | |
402 #endif // ABB_SEMAPHORE_PROTECTION | |
395 | 403 |
396 // a possible cause of the recovery is that ABB is on Oscas => switch from Oscas to CLK13 | 404 // a possible cause of the recovery is that ABB is on Oscas => switch from Oscas to CLK13 |
397 if (bRecoveryFlag) | 405 if (bRecoveryFlag) |
398 { | 406 { |
399 // RESTITUTE 13MHZ CLOCK TO ABB | 407 // RESTITUTE 13MHZ CLOCK TO ABB |
406 } | 414 } |
407 | 415 |
408 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. | 416 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. |
409 SPI_Ready_for_RDWR | 417 SPI_Ready_for_RDWR |
410 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | 418 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
411 | |
412 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
413 | |
414 // check if the semaphore has been correctly created and try to obtain it. | |
415 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
416 // as soon as the semaphore is released. | |
417 if(&abb_sem != 0) | |
418 { | |
419 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
420 } | |
421 #endif // ABB_SEMAPHORE_PROTECTION | |
422 | 419 |
423 ABB_SetPage(PAGE0); | 420 ABB_SetPage(PAGE0); |
424 | 421 |
425 // This transmission disables MADC,AFC,VDL,VUL modules. | 422 // This transmission disables MADC,AFC,VDL,VUL modules. |
426 ABB_WriteRegister(TOGBR1, 0x0155); | 423 ABB_WriteRegister(TOGBR1, 0x0155); |
615 // Reset VDLS and VULS bits | 612 // Reset VDLS and VULS bits |
616 // Write TOGBR1 register | 613 // Write TOGBR1 register |
617 // This transmission enables selected ABB modules. | 614 // This transmission enables selected ABB modules. |
618 ABB_WriteRegister(TOGBR1, 0x05); | 615 ABB_WriteRegister(TOGBR1, 0x05); |
619 | 616 |
620 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
621 // release the semaphore only if it has correctly been created. | |
622 if(&abb_sem != 0) | |
623 { | |
624 NU_Release_Semaphore(&abb_sem); | |
625 } | |
626 #endif // ABB_SEMAPHORE_PROTECTION | |
627 | |
628 // Stop the SPI clock | 617 // Stop the SPI clock |
629 #ifdef SPI_CLK_LOW_POWER | 618 #ifdef SPI_CLK_LOW_POWER |
630 SPI_CLK_DISABLE | 619 SPI_CLK_DISABLE |
631 #endif | 620 #endif |
632 } | 621 |
633 | 622 #if (ABB_SEMAPHORE_PROTECTION == 3) |
623 // release the semaphore only if it has correctly been created. | |
624 if(sem_status == NU_SUCCESS) | |
625 { | |
626 NU_Release_Semaphore(&abb_sem); | |
627 } | |
628 #endif // ABB_SEMAPHORE_PROTECTION | |
629 } | |
634 | 630 |
635 | 631 |
636 /*-----------------------------------------------------------------------*/ | 632 /*-----------------------------------------------------------------------*/ |
637 /* ABB_Read_ADC() */ | 633 /* ABB_Read_ADC() */ |
638 /* */ | 634 /* */ |
642 /* */ | 638 /* */ |
643 /*-----------------------------------------------------------------------*/ | 639 /*-----------------------------------------------------------------------*/ |
644 void ABB_Read_ADC(SYS_UWORD16 *Buff) | 640 void ABB_Read_ADC(SYS_UWORD16 *Buff) |
645 { | 641 { |
646 volatile SYS_UWORD16 status; | 642 volatile SYS_UWORD16 status; |
643 STATUS sem_status; | |
644 | |
645 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
646 | |
647 // check if the semaphore has been correctly created and try to obtain it. | |
648 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
649 // as soon as the semaphore is released. | |
650 | |
651 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
652 | |
653 #endif // ABB_SEMAPHORE_PROTECTION | |
647 | 654 |
648 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. | 655 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. |
649 SPI_Ready_for_RDWR | 656 SPI_Ready_for_RDWR |
650 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | 657 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
651 | |
652 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
653 | |
654 // check if the semaphore has been correctly created and try to obtain it. | |
655 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
656 // as soon as the semaphore is released. | |
657 if(&abb_sem != 0) | |
658 { | |
659 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
660 } | |
661 #endif // ABB_SEMAPHORE_PROTECTION | |
662 | 658 |
663 // This transmission changes the register page in the ABB for usp to pg0. | 659 // This transmission changes the register page in the ABB for usp to pg0. |
664 ABB_SetPage(PAGE0); | 660 ABB_SetPage(PAGE0); |
665 | 661 |
666 /* Read all ABB ADC registers */ | 662 /* Read all ABB ADC registers */ |
670 *Buff++ = ABB_ReadRegister(VBKPREG); | 666 *Buff++ = ABB_ReadRegister(VBKPREG); |
671 *Buff++ = ABB_ReadRegister(ADIN1REG); | 667 *Buff++ = ABB_ReadRegister(ADIN1REG); |
672 *Buff++ = ABB_ReadRegister(ADIN2REG); | 668 *Buff++ = ABB_ReadRegister(ADIN2REG); |
673 *Buff++ = ABB_ReadRegister(ADIN3REG); | 669 *Buff++ = ABB_ReadRegister(ADIN3REG); |
674 | 670 |
675 #if (ANLG_FAM ==1) | 671 #if (ANLG_FAM == 1) |
676 *Buff++ = ABB_ReadRegister(ADIN4XREG); | 672 *Buff++ = ABB_ReadRegister(ADIN4XREG); |
677 *Buff++ = ABB_ReadRegister(ADIN5YREG); | 673 *Buff++ = ABB_ReadRegister(ADIN5YREG); |
678 #elif (ANLG_FAM ==2) | 674 #elif (ANLG_FAM == 2) |
679 *Buff++ = ABB_ReadRegister(ADIN4REG); | 675 *Buff++ = ABB_ReadRegister(ADIN4REG); |
680 #elif (ANLG_FAM == 3) | 676 #elif (ANLG_FAM == 3) |
681 *Buff++ = ABB_ReadRegister(ADIN4REG); | 677 *Buff++ = ABB_ReadRegister(ADIN4REG); |
682 *Buff++ = ABB_ReadRegister(ADIN5REG); | 678 *Buff++ = ABB_ReadRegister(ADIN5REG); |
683 #endif // ANLG_FAM | 679 #endif // ANLG_FAM |
684 | 680 |
685 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
686 // release the semaphore only if it has correctly been created. | |
687 if(&abb_sem != 0) | |
688 { | |
689 NU_Release_Semaphore(&abb_sem); | |
690 } | |
691 #endif // ABB_SEMAPHORE_PROTECTION | |
692 | |
693 // Stop the SPI clock | 681 // Stop the SPI clock |
694 #ifdef SPI_CLK_LOW_POWER | 682 #ifdef SPI_CLK_LOW_POWER |
695 SPI_CLK_DISABLE | 683 SPI_CLK_DISABLE |
696 #endif | 684 #endif |
697 } | 685 |
698 | 686 #if (ABB_SEMAPHORE_PROTECTION == 3) |
687 // release the semaphore only if it has correctly been created. | |
688 if(sem_status == NU_SUCCESS) | |
689 { | |
690 NU_Release_Semaphore(&abb_sem); | |
691 } | |
692 #endif // ABB_SEMAPHORE_PROTECTION | |
693 } | |
699 | 694 |
700 | 695 |
701 /*-----------------------------------------------------------------------*/ | 696 /*-----------------------------------------------------------------------*/ |
702 /* ABB_Conf_ADC() */ | 697 /* ABB_Conf_ADC() */ |
703 /* */ | 698 /* */ |
707 /* */ | 702 /* */ |
708 /*-----------------------------------------------------------------------*/ | 703 /*-----------------------------------------------------------------------*/ |
709 void ABB_Conf_ADC(SYS_UWORD16 Channels, SYS_UWORD16 ItVal) | 704 void ABB_Conf_ADC(SYS_UWORD16 Channels, SYS_UWORD16 ItVal) |
710 { | 705 { |
711 volatile SYS_UWORD16 status; | 706 volatile SYS_UWORD16 status; |
707 STATUS sem_status; | |
712 SYS_UWORD16 reg_val; | 708 SYS_UWORD16 reg_val; |
709 | |
710 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
711 | |
712 // check if the semaphore has been correctly created and try to obtain it. | |
713 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
714 // as soon as the semaphore is released. | |
715 | |
716 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
717 | |
718 #endif // ABB_SEMAPHORE_PROTECTION | |
713 | 719 |
714 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. | 720 // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags. |
715 SPI_Ready_for_RDWR | 721 SPI_Ready_for_RDWR |
716 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | 722 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
717 | |
718 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
719 | |
720 // check if the semaphore has been correctly created and try to obtain it. | |
721 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
722 // as soon as the semaphore is released. | |
723 if(&abb_sem != 0) | |
724 { | |
725 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
726 } | |
727 #endif // ABB_SEMAPHORE_PROTECTION | |
728 | 723 |
729 // This transmission changes the register page in the ABB for usp to pg0. | 724 // This transmission changes the register page in the ABB for usp to pg0. |
730 ABB_SetPage(PAGE0); | 725 ABB_SetPage(PAGE0); |
731 | 726 |
732 /* select ADC channels to be converted */ | 727 /* select ADC channels to be converted */ |
742 if(ItVal == EOC_INTENA) | 737 if(ItVal == EOC_INTENA) |
743 ABB_WriteRegister(ITMASK, reg_val & EOC_INTENA); | 738 ABB_WriteRegister(ITMASK, reg_val & EOC_INTENA); |
744 else if(ItVal == EOC_INTMASK) | 739 else if(ItVal == EOC_INTMASK) |
745 ABB_WriteRegister(ITMASK, reg_val | EOC_INTMASK); | 740 ABB_WriteRegister(ITMASK, reg_val | EOC_INTMASK); |
746 | 741 |
747 #if (ABB_SEMAPHORE_PROTECTION == 3) | |
748 // release the semaphore only if it has correctly been created. | |
749 if(&abb_sem != 0) | |
750 { | |
751 NU_Release_Semaphore(&abb_sem); | |
752 } | |
753 #endif // ABB_SEMAPHORE_PROTECTION | |
754 | |
755 // Stop the SPI clock | 742 // Stop the SPI clock |
756 #ifdef SPI_CLK_LOW_POWER | 743 #ifdef SPI_CLK_LOW_POWER |
757 SPI_CLK_DISABLE | 744 SPI_CLK_DISABLE |
758 #endif | 745 #endif |
759 } | 746 |
760 | 747 #if (ABB_SEMAPHORE_PROTECTION == 3) |
761 | 748 // release the semaphore only if it has correctly been created. |
749 if(sem_status == NU_SUCCESS) | |
750 { | |
751 NU_Release_Semaphore(&abb_sem); | |
752 } | |
753 #endif // ABB_SEMAPHORE_PROTECTION | |
754 } | |
762 | 755 |
763 | 756 |
764 /*------------------------------------------------------------------------*/ | 757 /*------------------------------------------------------------------------*/ |
765 /* ABB_sleep() */ | 758 /* ABB_sleep() */ |
766 /* */ | 759 /* */ |
1068 /* */ | 1061 /* */ |
1069 /*------------------------------------------------------------------------*/ | 1062 /*------------------------------------------------------------------------*/ |
1070 void ABB_wa_VRPC(SYS_UWORD16 value) | 1063 void ABB_wa_VRPC(SYS_UWORD16 value) |
1071 { | 1064 { |
1072 volatile SYS_UWORD16 status; | 1065 volatile SYS_UWORD16 status; |
1066 STATUS sem_status; | |
1067 | |
1068 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
1069 | |
1070 // check if the semaphore has been correctly created and try to obtain it. | |
1071 // if the semaphore cannot be obtained, the task is suspended and then resumed | |
1072 // as soon as the semaphore is released. | |
1073 | |
1074 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | |
1075 | |
1076 #endif // ABB_SEMAPHORE_PROTECTION | |
1073 | 1077 |
1074 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | 1078 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. |
1075 SPI_Ready_for_WR | 1079 SPI_Ready_for_WR |
1076 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | 1080 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
1077 | 1081 |
1082 ABB_SetPage(PAGE1); | |
1083 | |
1084 #if (ANLG_FAM == 1) | |
1085 // This transmission initializes the VRPCCTL1 register. | |
1086 ABB_WriteRegister(VRPCCTRL1, value); | |
1087 | |
1088 #elif (ANLG_FAM == 2) | |
1089 // This transmission initializes the VRPCSIM register. | |
1090 ABB_WriteRegister(VRPCSIM, value); | |
1091 | |
1092 #elif (ANLG_FAM == 3) | |
1093 // This transmission initializes the VRPCSIMR register. | |
1094 ABB_WriteRegister(VRPCSIMR, value); | |
1095 | |
1096 #endif | |
1097 | |
1098 ABB_SetPage(PAGE0); | |
1099 | |
1100 // Stop the SPI clock | |
1101 #ifdef SPI_CLK_LOW_POWER | |
1102 SPI_CLK_DISABLE | |
1103 #endif | |
1104 | |
1078 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | 1105 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) |
1106 // release the semaphore only if it has correctly been created. | |
1107 if(sem_status == NU_SUCCESS) | |
1108 { | |
1109 NU_Release_Semaphore(&abb_sem); | |
1110 } | |
1111 #endif // ABB_SEMAPHORE_PROTECTION | |
1112 } | |
1113 | |
1114 | |
1115 /*-----------------------------------------------------------------------*/ | |
1116 /* ABB_Write_Uplink_Data() */ | |
1117 /* */ | |
1118 /* This function uses the SPI to write to ABB uplink buffer. */ | |
1119 /* */ | |
1120 /*-----------------------------------------------------------------------*/ | |
1121 void ABB_Write_Uplink_Data(SYS_UWORD16 *TM_ul_data) | |
1122 { | |
1123 SYS_UWORD8 i; | |
1124 volatile SYS_UWORD16 status; | |
1125 STATUS sem_status; | |
1126 | |
1127 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | |
1079 | 1128 |
1080 // check if the semaphore has been correctly created and try to obtain it. | 1129 // check if the semaphore has been correctly created and try to obtain it. |
1081 // if the semaphore cannot be obtained, the task is suspended and then resumed | 1130 // if the semaphore cannot be obtained, the task is suspended and then resumed |
1082 // as soon as the semaphore is released. | 1131 // as soon as the semaphore is released. |
1083 if(&abb_sem != 0) | 1132 |
1084 { | 1133 sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); |
1085 NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); | 1134 |
1086 } | 1135 #endif // ABB_SEMAPHORE_PROTECTION |
1087 #endif // ABB_SEMAPHORE_PROTECTION | 1136 |
1088 | 1137 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. |
1089 ABB_SetPage(PAGE1); | 1138 SPI_Ready_for_WR |
1090 | 1139 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; |
1091 #if (ANLG_FAM == 1) | 1140 |
1092 // This transmission initializes the VRPCCTL1 register. | 1141 // Select Page 0 for TOGBR2 |
1093 ABB_WriteRegister(VRPCCTRL1, value); | |
1094 | |
1095 #elif (ANLG_FAM == 2) | |
1096 // This transmission initializes the VRPCSIM register. | |
1097 ABB_WriteRegister(VRPCSIM, value); | |
1098 | |
1099 #elif (ANLG_FAM == 3) | |
1100 // This transmission initializes the VRPCSIMR register. | |
1101 ABB_WriteRegister(VRPCSIMR, value); | |
1102 | |
1103 #endif | |
1104 | |
1105 ABB_SetPage(PAGE0); | 1142 ABB_SetPage(PAGE0); |
1106 | 1143 |
1107 #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) | 1144 // Initialize pointer of burst buffer 1 : IBUFPTR is bit 10 of TOGBR2 |
1108 // release the semaphore only if it has correctly been created. | 1145 ABB_WriteRegister(TOGBR2, 0x10); |
1109 if(&abb_sem != 0) | 1146 |
1110 { | 1147 // Clear, assuming that it works like IBUFPTR of Vega |
1111 NU_Release_Semaphore(&abb_sem); | 1148 ABB_WriteRegister(TOGBR2, 0x0); |
1112 } | 1149 |
1113 #endif // ABB_SEMAPHORE_PROTECTION | 1150 // Write the ramp data |
1151 for (i=0;i<16;i++) | |
1152 ABB_WriteRegister(BULDATA1_2, TM_ul_data[i]>>6); | |
1114 | 1153 |
1115 // Stop the SPI clock | 1154 // Stop the SPI clock |
1116 #ifdef SPI_CLK_LOW_POWER | 1155 #ifdef SPI_CLK_LOW_POWER |
1117 SPI_CLK_DISABLE | 1156 SPI_CLK_DISABLE |
1118 #endif | 1157 #endif |
1119 } | 1158 |
1120 | 1159 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) |
1121 | 1160 // release the semaphore only if it has correctly been created. |
1122 /*-----------------------------------------------------------------------*/ | 1161 if(sem_status == NU_SUCCESS) |
1123 /* ABB_Write_Uplink_Data() */ | 1162 { |
1124 /* */ | 1163 NU_Release_Semaphore(&abb_sem); |
1125 /* This function uses the SPI to write to ABB uplink buffer. */ | 1164 } |
1126 /* */ | 1165 #endif // ABB_SEMAPHORE_PROTECTION |
1127 /*-----------------------------------------------------------------------*/ | |
1128 void ABB_Write_Uplink_Data(SYS_UWORD16 *TM_ul_data) | |
1129 { | |
1130 SYS_UWORD8 i; | |
1131 volatile SYS_UWORD16 status; | |
1132 | |
1133 // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags. | |
1134 SPI_Ready_for_WR | |
1135 status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; | |
1136 | |
1137 // Select Page 0 for TOGBR2 | |
1138 ABB_SetPage(PAGE0); | |
1139 | |
1140 // Initialize pointer of burst buffer 1 : IBUFPTR is bit 10 of TOGBR2 | |
1141 ABB_WriteRegister(TOGBR2, 0x10); | |
1142 | |
1143 // Clear, assuming that it works like IBUFPTR of Vega | |
1144 ABB_WriteRegister(TOGBR2, 0x0); | |
1145 | |
1146 // Write the ramp data | |
1147 for (i=0;i<16;i++) | |
1148 ABB_WriteRegister(BULDATA1_2, TM_ul_data[i]>>6); | |
1149 | |
1150 // Stop the SPI clock | |
1151 #ifdef SPI_CLK_LOW_POWER | |
1152 SPI_CLK_DISABLE | |
1153 #endif | |
1154 } | 1166 } |
1155 | 1167 |
1156 //////////////////////// IDEV-INLO integration of sleep mode for Syren /////////////////////////////////////// | 1168 //////////////////////// IDEV-INLO integration of sleep mode for Syren /////////////////////////////////////// |
1157 | 1169 |
1158 #if (ANLG_FAM == 3) | 1170 #if (ANLG_FAM == 3) |
1207 #elif((ANLG_FAM == 2) || (ANLG_FAM == 3)) | 1219 #elif((ANLG_FAM == 2) || (ANLG_FAM == 3)) |
1208 ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); | 1220 ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001); |
1209 #endif | 1221 #endif |
1210 } | 1222 } |
1211 #endif | 1223 #endif |
1212 | |
1213 | |
1214 |