summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-10-09 13:05:49 -0700
committerVincent Palatin <vpalatin@chromium.org>2012-10-10 11:41:56 -0700
commitcb67e82b7a921768b95d0e0ab862d0fcb5cb80e7 (patch)
treedd00c2490882a1fef79cdc93383e3aa0bab6a455
parent8c43024e2fae929ffc621b7dea0d7367d3510ac8 (diff)
downloadchrome-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.c76
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.
- */
}
}