mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 18:35:28 +00:00
link: Disable interrupts while reading/writing bits via onewire
When reading, the line must be sampled in a narrow timing window after the output pulse. Interrupts or context switches during this time corrupt the data. Similarly, when writing, the difference between a 0-bit and a 1-bit is the length of the output pulse. So a context switch or interrupt there can turn a 1-bit into a 0-bit. BUG=chrome-os-partner:15507 BRANCH=link TEST=manual 0. plug in AC power 1. hold down shift key for the duration of this test 2. powerled yellow 3. powerled red 4. repeat steps 2-3 several times 5. release shift key Power adapter LED should toggle color each time. (It may also toggle to the normally expected color during this experiment, if the charging task updates it.) Power adapter LED should NOT turn off during this test. Change-Id: Ief11e6e9a5b07aa3a25c60c50e4e7744a4705713 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/38925 Reviewed-by: Yung-Chieh Lo <yjlou@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define ONEWIRE_PIN (1<<2) /* One-wire pin mask (on GPIO H) */
|
||||
@@ -56,6 +57,12 @@ static int readbit(void)
|
||||
{
|
||||
int bit;
|
||||
|
||||
/*
|
||||
* The delay between sending the output pulse and reading the bit is
|
||||
* extremely timing sensitive, so disable interrupts.
|
||||
*/
|
||||
interrupt_disable();
|
||||
|
||||
/* Output low */
|
||||
output0(T_RL);
|
||||
|
||||
@@ -65,6 +72,13 @@ static int readbit(void)
|
||||
/* Read bit */
|
||||
bit = readline();
|
||||
|
||||
/*
|
||||
* Enable interrupt as soon as we've read the bit. The delay to the
|
||||
* end of the timeslot is a lower bound, so additional latency here is
|
||||
* harmless.
|
||||
*/
|
||||
interrupt_enable();
|
||||
|
||||
/* Delay to end of timeslot */
|
||||
udelay(T_SLOT - T_MSR);
|
||||
return bit;
|
||||
@@ -75,13 +89,25 @@ static int readbit(void)
|
||||
*/
|
||||
static void writebit(int bit)
|
||||
{
|
||||
/*
|
||||
* The delays in the output-low signal for sending 0 and 1 bits are
|
||||
* extremely timing sensitive, so disable interrupts during that time.
|
||||
* Interrupts can be enabled again as soon as the output is switched
|
||||
* back to open-drain, since the delay for the rest of the timeslot is
|
||||
* a lower bound.
|
||||
*/
|
||||
if (bit) {
|
||||
interrupt_disable();
|
||||
output0(T_W1L);
|
||||
interrupt_enable();
|
||||
udelay(T_SLOT - T_W1L);
|
||||
} else {
|
||||
interrupt_disable();
|
||||
output0(T_W0L);
|
||||
interrupt_enable();
|
||||
udelay(T_SLOT - T_W0L);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int onewire_reset(void)
|
||||
|
||||
Reference in New Issue
Block a user