опыты с железом (lpc2106) LPC2106, кварц 10 МГц, частота процессора и таймера - 60 МГц.
IAR там, flash утилита, все вроде чудненько...
простая задача для разминки
нога P0_18 (capture 3). Хочу отследить импульс.
Отловить фронт, потом спад. На капчур заведено неспроста (заранее подумал).
Ловим спад по capture (опросом), а потом программно (тем же опросом) - фронт
итак
PINSEL1_bit.P0_18 = 1; // pin function
T1CCR = 0x0C00; // falling edge and interrupt
...
// clear interrupt flag
T1IR = 0xFF;
// wait flag on capture event
while (!(T1IR & 0x80));
// а теперь отследить высокий уровень
while (!IOPIN_bit.P0_18);
вроде ничего крамольного. такой алгоритм обусловлен фразой даташита из описания регистра IOPIN:
"GPIO Pin value register. The current state of the port pins can always be read from the register, regardless of pin direction and mode" (mode - это, надо понимать, function этого пина)
только фиг там, не отслеживает фронт (через while (IOPIN...) не проходит)
решение - этот самый mode перед опросом опять делать обычной ногой ввода вывода. т.е.
PINSEL1_bit.P0_18 = 0; // pin function
хм, мы не гордые, можно и переключить mode...
(но осадок остался)
ладно, идем дальше
надо замутить точную паузу. Лучший выбор - match.
Без никаких прерываний. Опросом.
T1MCR = 1; // interrupt on match on MATCH0
T1MR0 = T1TC + 12300; // where to go
//clear interrupt flag
T1IR = 0xFF;
// NOW WAIT FOR "WAKE-UP" FLAG TO APPEAR
while (!(T1IR & 0x01));
ан нет, можно ждать очень долго.
while не работает
Два часа разбирательств - так ничего и не понятно - но все работает.
"Все лишь" надо было притормозить таймер.
T1MCR = 1; // interrupt on match on MATCH0
T1MR0 = 12300;
T1TCR = 0; // stop timer
// clear interrupts flags here
T1IR = 0xFF;
T1TC = 0;
T1TCR = 1;
while (!(T1IR & 0x01));
попутно (уж коли тормозим) код немного упростился - таймер просто сбрасывается и match "чистый".
только вот таймер останавливать все равно приходится. С чего вдруг?
фигня какая-то... ничего такого в даташитах не прописано.
(но они по жизни скупые, тем бОльшую цену имеет каждое слово)
давненько не читал почту с яху-группы, пора.
и все оказалось немного серьезнее
вот небольшое резюме свежего треда - рекомендую настоятельно
это послание от 13 окт. (на yahoo эхе еще нет)
суть - баги в железе есть (Филипс это признает, но ерраты пока нет). теряются (и очень конкретно) прерывания по таймерам и уартам
(там где несколько флагов в одном регистре)
для таймеров один из workaroundов для одного из случаев -
(при)останавливать таймер. (похоже как у меня)
This is a forwarded message
From: Robert Adsett
To: lpc2000@yahoogroups.com
Date: Wednesday, October 13, 2004, 1:57:37 AM
Subject: [lpc2000] Re: Undocumented Timer Interrupt Feature, or Silicon Bug...
===8<==============Original message text===============
At 09:09 PM 10/12/04 +0000, you wrote:
>There is a silicon bug, which Philips has confirmed, but has yet > to publish.
Note to Philips: Timely publication of errata is a MUST. If nothing else it saves a lot of bloody foreheads.
>If the timer hardware triggers an interrupt at the same time that > the core is writing to the timer IR register to clear an >interrupt on a different channel, the new interrupt does not get >set. This problem can occur with an input capture, as well as >with a match. That is a bit more difficult to work around.
That certainly explains it.
>As for there being a similar problem on the UART IIR, do you have > a reproducible situation to determine this?
Yes, I did. The situation came up while working with serial port
interrupts (naturally). It required that both transmit and receive
interrupts be on simultaneously. I then just had a simple echo program running on the micro and had the terminal emulator on the PC dumping a file continuously out the serial port. At some point the echo would stop (it could take several Mbytes). As in the timer case I couldn't see any possible way for the SW to miss the interrupt completely.
Two workarounds seems to 'fix' the problem
- one was to check the transmit ready flags in the receive interrupt and restart the transmission if a transmit interrupt was missed,
- the second was to only service a single interrupt source on each interrupt (only read IIR once)
The first workaround is obviously problematic since it requires a received character to restart the transmit. The second one appeared to be successful, but since the bug appeared to be somewhat timing sensitive I don't know for sure if it was eliminated or simply had it's probability drop by an order of magnitude or so.
Note that the nature of the test would mask any missing receive interrupts if only an occasional character was dropped. Receive should be more robust anyway since each receipt should conceivably re-trigger the interrupt whereas the transmit interrupt only fires once.
I don't think I kept the original failing code (silly me) but I should be able to reproduce it if anyone can make use of it.
I first reported on this in this group back on June 23 (see thread "Missing THRE interrupt?"). It was met with resounding silence so I thought I was the only one seeing anything like it until this timer interrupt thread.
I've been uncomfortable that I haven't been able to pin down a definitive cause but I've had other things to do so it's been on the back burner with a mental "Here be dragons!" sign for future attention. You have just given me hope that the cause may yet be found (and more importantly confirmed).
>I suspect there are probably other registers (which can be
> written to by both the core and peripheral hardware) which
> exhibit a similar problem. I don't know how much Philips has
> determined about the specifics and extent of this bug, since
> first confirming its existence.
Certainly if it exists for one peripheral it raises the possibility that it has occurred in others.
If I knew for sure that the problem was some sort of race condition there is a chance I could work around it.
Robert"
к чему все это?
как говорится, "Praemonitus praemunitus" (предупрежден - значит вооружен)
с ув.