38 | | int i = MCF5282_PIT3_PCNTR; |
39 | | if (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) |
40 | | i = MCF5282_PIT3_PCNTR - USEC_PER_TICK; |
41 | | return (USEC_PER_TICK - i) * 1000; |
| 38 | uint32_t tdiff; |
| 39 | |
| 40 | /* Details to consider here: |
| 41 | * |
| 42 | * - PIT is 16-bit. To properly handle differences of two |
| 43 | * 16-bit numbers (which requires 17-bits) we want to |
| 44 | * do the arithmetic in a wider data type. PIT reading |
| 45 | * is a unsigned 16-bit count. |
| 46 | * |
| 47 | * => must make sure PIT is a *unsigned* 16-bit type. Otherwise |
| 48 | * values get sign-extended when converted to wider type |
| 49 | * (regardless of the signedness of wider type): |
| 50 | * |
| 51 | * (unsigned)(signed short)0xffff -> 0xffffffff. |
| 52 | * |
| 53 | * and thus |
| 54 | * |
| 55 | * (uint32_t)(int16_t)65535 - (uin32_t)(int16_t)1 |
| 56 | * |
| 57 | * would yield 0xfffffffe, not 65534! |
| 58 | * |
| 59 | * |
| 60 | * - PIT counts backwards from PMR -> zero, hence |
| 61 | * |
| 62 | * now - tick_base = (PMR - now) - (PMR - tick_base) = tick_base - now; |
| 63 | * |
| 64 | * result may be negative (if rolled-over). |
| 65 | * |
| 66 | * - PIF flag, counter and PCNTR_AT_TICK must all |
| 67 | * be read atomically - otherwise an interrupt may |
| 68 | * have altered their values while we're looking. |
| 69 | * |
| 70 | * NOTE: score framework calling this routine disables |
| 71 | * interrupts during execution of this callout. |
| 72 | * |
| 73 | * - Last but not least, rollover might have happened |
| 74 | * just between reading counter and PIF flag; hence |
| 75 | * we have to re-read the counter if PIF is set. |
| 76 | * |
| 77 | */ |
| 78 | |
| 79 | /* obtain current value */ |
| 80 | tdiff = (uint16_t)MCF5282_PIT3_PCNTR; |
| 81 | |
| 82 | if (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) { |
| 83 | /* rollover may just have happened; |
| 84 | * must reload PCNTR. |
| 85 | */ |
| 86 | tdiff = + (uint32_t)(uint16_t)MCF5282_PIT3_PMR |
| 87 | + (uint32_t)(uint16_t)PCNTR_AT_TICK |
| 88 | - (uint32_t)(uint16_t)MCF5282_PIT3_PCNTR; |
| 89 | } else { |
| 90 | tdiff = + (uint32_t)(uint16_t)PCNTR_AT_TICK - tdiff; |
| 91 | } |
| 92 | |
| 93 | return tdiff * 1000; |