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