diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2012-10-09 13:05:49 -0700 |
---|---|---|
committer | Vincent Palatin <vpalatin@chromium.org> | 2012-10-10 11:41:56 -0700 |
commit | cb67e82b7a921768b95d0e0ab862d0fcb5cb80e7 (patch) | |
tree | dd00c2490882a1fef79cdc93383e3aa0bab6a455 | |
parent | 8c43024e2fae929ffc621b7dea0d7367d3510ac8 (diff) | |
download | chrome-ec-cb67e82b7a921768b95d0e0ab862d0fcb5cb80e7.tar.gz |
stm32: fix race condition enabling keyboard interrupt
Previously, if a key was pressed after the last polling but
the interrupts were fully enabled, we were missing the edge.
So dropping the key press event and seeing only the key release.
Now we check if keys are down before waiting for the next interrupt,
if any, we re-start polling immediatly.
The row state reading code is unchanged, just moved to a function
in order to re-use it.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=snow
BUG=chrome-os-partner:7484 chrome-os-partner:12179
TEST=type on the keyboard and do not see any missing key presses.
On instrumented board, record the the matrix scans with a logic analyzer
and stare at the waveforms.
Change-Id: I33a9fb23825626ae5a8482f836482af79702fc17
Reviewed-on: https://gerrit.chromium.org/gerrit/35054
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | chip/stm32/keyboard_scan.c | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/chip/stm32/keyboard_scan.c b/chip/stm32/keyboard_scan.c index de537cc931..0715de68c5 100644 --- a/chip/stm32/keyboard_scan.c +++ b/chip/stm32/keyboard_scan.c @@ -238,6 +238,40 @@ static int check_warm_reboot_keys(void) return 0; } +static uint8_t read_raw_row_state(void) +{ + uint16_t tmp; + uint8_t r = 0; + + tmp = STM32_GPIO_IDR(C); + /* KB_COL00:04 = PC8:12 */ + if (tmp & (1 << 8)) + r |= 1 << 0; + if (tmp & (1 << 9)) + r |= 1 << 1; + if (tmp & (1 << 10)) + r |= 1 << 2; + if (tmp & (1 << 11)) + r |= 1 << 3; + if (tmp & (1 << 12)) + r |= 1 << 4; + /* KB_COL05:06 = PC14:15 */ + if (tmp & (1 << 14)) + r |= 1 << 5; + if (tmp & (1 << 15)) + r |= 1 << 6; + + tmp = STM32_GPIO_IDR(D); + /* KB_COL07 = PD2 */ + if (tmp & (1 << 2)) + r |= 1 << 7; + + /* Invert it so 0=not pressed, 1=pressed */ + r ^= 0xff; + + return r; +} + /* Returns 1 if any key is still pressed. 0 if no key is pressed. */ static int check_keys_changed(void) { @@ -247,38 +281,12 @@ static int check_keys_changed(void) int num_press = 0; for (c = 0; c < KB_OUTPUTS; c++) { - uint16_t tmp; - /* Select column, then wait a bit for it to settle */ select_column(c); udelay(50); - r = 0; - tmp = STM32_GPIO_IDR(C); - /* KB_COL00:04 = PC8:12 */ - if (tmp & (1 << 8)) - r |= 1 << 0; - if (tmp & (1 << 9)) - r |= 1 << 1; - if (tmp & (1 << 10)) - r |= 1 << 2; - if (tmp & (1 << 11)) - r |= 1 << 3; - if (tmp & (1 << 12)) - r |= 1 << 4; - /* KB_COL05:06 = PC14:15 */ - if (tmp & (1 << 14)) - r |= 1 << 5; - if (tmp & (1 << 15)) - r |= 1 << 6; - - tmp = STM32_GPIO_IDR(D); - /* KB_COL07 = PD2 */ - if (tmp & (1 << 2)) - r |= 1 << 7; - - /* Invert it so 0=not pressed, 1=pressed */ - r ^= 0xff; + r = read_raw_row_state(); + /* Mask off keys that don't exist so they never show * as pressed */ r &= actual_key_mask[c]; @@ -404,7 +412,13 @@ void keyboard_scan_task(void) wait_for_interrupt(); mutex_unlock(&scanning_enabled); - task_wait_event(-1); + /* + * if a key was pressed after the last polling, + * re-start immediatly polling instead of waiting + * for the next interrupt. + */ + if (!read_raw_row_state()) + task_wait_event(-1); enter_polling_mode(); /* Busy polling keyboard state. */ @@ -427,10 +441,6 @@ void keyboard_scan_task(void) } } } - /* TODO: (crosbug.com/p/7484) A race condition here. - * If a key state is changed here (before interrupt is - * enabled), it will be lost. - */ } } |