[simio] Fix timer capturing by software
This commit is contained in:
parent
d49dcefec6
commit
8db02ae3d4
|
@ -168,14 +168,40 @@ static int config_irq(int *irq, char **arg_text)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void trigger_capture(struct timer *tr, int which, int oldval, int value)
|
||||
{
|
||||
uint16_t edge_flags = 0;
|
||||
|
||||
tr->ctls[which] &= ~CCI;
|
||||
if (value)
|
||||
tr->ctls[which] |= CCI;
|
||||
|
||||
if (oldval && !value)
|
||||
edge_flags |= CM1;
|
||||
if (!oldval && value)
|
||||
edge_flags |= CM0;
|
||||
|
||||
printc_dbg("Timer channel %d: %s => %s\n",
|
||||
which, oldval ? "H" : "L", value ? "H" : "L");
|
||||
|
||||
if ((tr->ctls[which] & edge_flags) && (tr->ctls[which] & CAP)) {
|
||||
if (tr->ctls[which] & CCIFG) {
|
||||
printc_dbg("Timer capture overflow\n");
|
||||
tr->ctls[which] |= COV;
|
||||
} else {
|
||||
printc_dbg("Timer capture interrupt triggered\n");
|
||||
tr->ccrs[which] = tr->tar;
|
||||
tr->ctls[which] |= CCIFG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int config_channel(struct timer *tr, char **arg_text)
|
||||
{
|
||||
char *which_text = get_arg(arg_text);
|
||||
char *value_text = get_arg(arg_text);
|
||||
address_t which;
|
||||
address_t value;
|
||||
int oldval;
|
||||
uint16_t edge_flags = 0;
|
||||
|
||||
if (!(which_text && value_text)) {
|
||||
printc_err("timer: config: expected channel and value\n");
|
||||
|
@ -199,29 +225,7 @@ static int config_channel(struct timer *tr, char **arg_text)
|
|||
return -1;
|
||||
}
|
||||
|
||||
oldval = tr->ctls[which] & CCI;
|
||||
tr->ctls[which] &= ~CCI;
|
||||
if (value)
|
||||
tr->ctls[which] |= CCI;
|
||||
|
||||
if (oldval && !value)
|
||||
edge_flags |= CM1;
|
||||
if (!oldval && value)
|
||||
edge_flags |= CM0;
|
||||
|
||||
printc_dbg("Timer channel %d: %s => %s\n",
|
||||
which, oldval ? "H" : "L", value ? "H" : "L");
|
||||
|
||||
if ((tr->ctls[which] & edge_flags) && (tr->ctls[which] & CAP)) {
|
||||
if (tr->ctls[which] & CCIFG) {
|
||||
printc_dbg("Timer capture overflow\n");
|
||||
tr->ctls[which] |= COV;
|
||||
} else {
|
||||
printc_dbg("Timer capture interrupt triggered\n");
|
||||
tr->ccrs[which] = tr->tar;
|
||||
tr->ctls[which] |= CCIFG;
|
||||
}
|
||||
}
|
||||
trigger_capture(tr, which, tr->ctls[which] & CCI, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -311,9 +315,12 @@ static int timer_write(struct simio_device *dev,
|
|||
if (addr >= tr->base_addr + 2 &&
|
||||
addr < tr->base_addr + (tr->size << 1) + 2) {
|
||||
int index = ((addr & 0xf) - 2) >> 1;
|
||||
uint16_t oldval = tr->ctls[index];
|
||||
|
||||
tr->ctls[index] = (data & 0xf9f7) |
|
||||
(tr->ctls[index] & 0x0608);
|
||||
tr->ctls[index] = (data & 0xf9f7) | (oldval & 0x0608);
|
||||
/* Check capture initiated by Software */
|
||||
if ((data & (CAP | CCIS1)) == (CAP | CCIS1))
|
||||
trigger_capture(tr, index, oldval & CCI, data & CCIS0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -505,7 +505,79 @@ static void test_timer_divider()
|
|||
assert(read_timer(dev, TxR) == 10);
|
||||
}
|
||||
|
||||
static void test_timer_capture()
|
||||
static void test_timer_capture_by_software()
|
||||
{
|
||||
dev = create_timer("");
|
||||
|
||||
/* Continuous mode, ACLK, clear */
|
||||
write_timer(dev, TxCTL, MC1 | TASSEL0 | TACLR);
|
||||
|
||||
/* Capture mode, input GND, both edge */
|
||||
write_timer(dev, TxCCTL(0), CAP | CCIS1 | CM1 | CM0);
|
||||
step_aclk(dev, 10);
|
||||
// Rising edge.
|
||||
write_timer(dev, TxCCTL(0), read_timer(dev, TxCCTL(0)) | CCIS0);
|
||||
assert(read_timer(dev, TxCCTL(0)) & CCI);
|
||||
assert_not(read_timer(dev, TxCCTL(0)) & COV);
|
||||
assert(read_timer(dev, TxCCTL(0)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(0)) == 10);
|
||||
|
||||
write_timer(dev, TxCCTL(0), read_timer(dev, TxCCTL(0)) & ~CCIFG);
|
||||
step_aclk(dev, 10);
|
||||
// Falling edge.
|
||||
write_timer(dev, TxCCTL(0), read_timer(dev, TxCCTL(0)) & ~CCIS0);
|
||||
assert_not(read_timer(dev, TxCCTL(0)) & CCI);
|
||||
assert_not(read_timer(dev, TxCCTL(0)) & COV);
|
||||
assert(read_timer(dev, TxCCTL(0)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(0)) == 20);
|
||||
|
||||
// Keep CCIFG on and capture causes COV */
|
||||
step_aclk(dev, 10);
|
||||
// Rising edge.
|
||||
write_timer(dev, TxCCTL(0), read_timer(dev, TxCCTL(0)) | CCIS0);
|
||||
assert(read_timer(dev, TxCCTL(0)) & CCI);
|
||||
assert(read_timer(dev, TxCCTL(0)) & COV);
|
||||
assert(read_timer(dev, TxCCTL(0)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(0)) == 20);
|
||||
|
||||
/* Capture mode, input GND, rising edge */
|
||||
write_timer(dev, TxCCTL(1), CAP | CCIS1 | CM0);
|
||||
// Rising edge.
|
||||
write_timer(dev, TxCCTL(1), read_timer(dev, TxCCTL(1)) | CCIS0);
|
||||
assert(read_timer(dev, TxCCTL(1)) & CCI);
|
||||
assert_not(read_timer(dev, TxCCTL(1)) & COV);
|
||||
assert(read_timer(dev, TxCCTL(1)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(1)) == 30);
|
||||
|
||||
write_timer(dev, TxCCTL(1), read_timer(dev, TxCCTL(1)) & ~CCIFG);
|
||||
step_aclk(dev, 10);
|
||||
// Falling edge.
|
||||
write_timer(dev, TxCCTL(1), read_timer(dev, TxCCTL(1)) & ~CCIS0);
|
||||
assert_not(read_timer(dev, TxCCTL(1)) & CCI);
|
||||
assert_not(read_timer(dev, TxCCTL(1)) & COV);
|
||||
assert_not(read_timer(dev, TxCCTL(1)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(1)) == 30);
|
||||
|
||||
/* Capture mode, input GND, falling edge */
|
||||
write_timer(dev, TxCCTL(2), CAP | CCIS1 | CM1);
|
||||
// Rising edge.
|
||||
write_timer(dev, TxCCTL(2), read_timer(dev, TxCCTL(2)) | CCIS0);
|
||||
assert(read_timer(dev, TxCCTL(2)) & CCI);
|
||||
assert_not(read_timer(dev, TxCCTL(2)) & COV);
|
||||
assert_not(read_timer(dev, TxCCTL(2)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(2)) == 0);
|
||||
|
||||
step_aclk(dev, 10);
|
||||
// Falling edge.
|
||||
write_timer(dev, TxCCTL(2), read_timer(dev, TxCCTL(2)) & ~CCIS0);
|
||||
assert_not(read_timer(dev, TxCCTL(2)) & CCI);
|
||||
assert_not(read_timer(dev, TxCCTL(2)) & COV);
|
||||
assert(read_timer(dev, TxCCTL(2)) & CCIFG);
|
||||
assert(read_timer(dev, TxCCR(2)) == 50);
|
||||
}
|
||||
|
||||
|
||||
static void test_timer_capture_by_signal()
|
||||
{
|
||||
dev = create_timer("");
|
||||
|
||||
|
@ -685,6 +757,7 @@ int main(int argc, char **argv)
|
|||
RUN_TEST(test_timer_up_change_period);
|
||||
RUN_TEST(test_timer_updown_change_period);
|
||||
RUN_TEST(test_timer_divider);
|
||||
RUN_TEST(test_timer_capture);
|
||||
RUN_TEST(test_timer_capture_by_software);
|
||||
RUN_TEST(test_timer_capture_by_signal);
|
||||
RUN_TEST(test_timer_compare);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue