summaryrefslogtreecommitdiff
path: root/chip/stm32
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-10-09 13:05:49 -0700
committerGerrit <chrome-bot@google.com>2012-10-10 14:53:16 -0700
commit160b343e7c75a939d64ef92146c78db97498c9d6 (patch)
treee7bba985e53c5dbaf507720e5f74fabe14b6affd /chip/stm32
parent8d187addc8ca7f8379185b33171995e1b113e55f (diff)
downloadchrome-ec-160b343e7c75a939d64ef92146c78db97498c9d6.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> (Note: This patch was originally submitted in the firmware-snow-2695.B branch, but needed some re-factoring to merge cleanly into ToT) 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: I98dc4c3af9611a276b960887384a6304b91d8b30 Reviewed-on: https://gerrit.chromium.org/gerrit/35168 Commit-Ready: David Hendricks <dhendrix@chromium.org> Reviewed-by: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'chip/stm32')
-rw-r--r--chip/stm32/keyboard_scan.c85
1 files changed, 46 insertions, 39 deletions
diff --git a/chip/stm32/keyboard_scan.c b/chip/stm32/keyboard_scan.c
index 23513ee4c0..243292287a 100644
--- a/chip/stm32/keyboard_scan.c
+++ b/chip/stm32/keyboard_scan.c
@@ -282,6 +282,44 @@ static void print_state(const uint8_t *state, const char *msg)
CPUTS("]\n");
}
+static uint8_t read_raw_row_state(void)
+{
+ uint16_t tmp;
+ uint8_t r = 0;
+
+ /*
+ * TODO(sjg@chromium.org): This code can be improved by doing
+ * the job in 3 shift/or operations.
+ */
+ 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;
+}
+
/**
* Read the raw keyboard matrix state.
*
@@ -299,42 +337,11 @@ static int read_matrix(uint8_t *state)
int pressed = 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(config.output_settle_us);
- /*
- * TODO(sjg@chromium.org): This code can be improved by doing
- * the job in 3 shift/or operations.
- */
- 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();
#ifdef OR_WITH_CURRENT_STATE_FOR_TESTING
/* KLUDGE - or current state in, so we can make sure
@@ -512,8 +519,13 @@ static void scan_keyboard(void)
setup_interrupts();
mutex_unlock(&scanning_enabled);
- /* Wait until we get an interrupt */
- 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();
@@ -543,11 +555,6 @@ static void scan_keyboard(void)
wait_time = config.min_post_scan_delay_us;
task_wait_event(wait_time);
}
- /*
- * TODO: (crosbug.com/p/7484) A race condition here.
- * If a key state is changed here (before interrupt is
- * enabled), it will be lost.
- */
}
void keyboard_scan_task(void)