mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +00:00
base-hw imx epit-timer: fix duration calculation
The timer used to read the counter first and then the IRQ status. This could cause a non-wrapped counter value to be considered a wrapped counter value, leading to bogus timeout durations. This commit fixes the bug and documents the used timer mode in the driver in order to make future debugging of the driver easier. Ref #4959
This commit is contained in:
parent
9d98e8ac01
commit
90ba794e8e
@ -36,6 +36,19 @@ Board::Timer::Timer(unsigned)
|
||||
|
||||
void Board::Timer::init()
|
||||
{
|
||||
/*
|
||||
* Used timer mode:
|
||||
*
|
||||
* - Set CNT to 0xffffffff whenever CR.EN goes from 0 to 1 (CR.EN_MOD = 1).
|
||||
* This happens only once: at construction time.
|
||||
* - CNT is counting downwards with timer frequency.
|
||||
* - When CNT reaches 0 it rolls over to 0xffffffff (CR.RLD = 0).
|
||||
* - When writing LR, also set CNT to new LR value (CR.IOVW = 1). This
|
||||
* happens whenever a timeout is programmed.
|
||||
* - Trigger IRQ when CNT == CMPR (CR.OCI_EN = 1). CMPR is always set to
|
||||
* 0xffffffff.
|
||||
*/
|
||||
|
||||
reset();
|
||||
|
||||
Cr::access_t cr = read<Cr>();
|
||||
@ -81,8 +94,8 @@ time_t Timer::_max_value() const {
|
||||
time_t Timer::_duration() const
|
||||
{
|
||||
using Device = Board::Timer;
|
||||
Device::Cnt::access_t last = (Device::Cnt::access_t) _last_timeout_duration;
|
||||
Device::Cnt::access_t cnt = _device.read<Device::Cnt>();
|
||||
return (_device.read<Device::Sr::Ocif>()) ? _max_value() - cnt + last
|
||||
Device::Cnt::access_t const last = (Device::Cnt::access_t) _last_timeout_duration;
|
||||
Device::Cnt::access_t const cnt = _device.read<Device::Cnt>();
|
||||
return (_device.read<Device::Sr::Ocif>()) ? _max_value() - _device.read<Device::Cnt>() + last
|
||||
: last - cnt;
|
||||
}
|
||||
|
@ -41,11 +41,6 @@ struct Board::Timer : Genode::Mmio
|
||||
|
||||
struct Oci_en : Bitfield<2, 1> { }; /* interrupt on compare */
|
||||
|
||||
struct Rld : Bitfield<3, 1> /* reload or roll-over */
|
||||
{
|
||||
enum { RELOAD_FROM_LR = 1 };
|
||||
};
|
||||
|
||||
struct Prescaler : Bitfield<4, 12> /* clock input divisor */
|
||||
{
|
||||
enum { DIVIDE_BY_1 = 0 };
|
||||
|
Loading…
x
Reference in New Issue
Block a user