Skip to content

Commit 02ff796

Browse files
committed
mega: continous twi_listen packets prevented mdb response
Failed to identify root cause. Side-fixed with: - twi_step will only write response if mdb is in idle state - successful mdb response will also ship any outgoing twi_data Important takeaway for mega-client: expect TWI_DATA field in any response. Buzzword: priority inversion
1 parent 0309542 commit 02ff796

File tree

8 files changed

+54
-45
lines changed

8 files changed

+54
-45
lines changed

hardware/mega-client/mega.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -444,18 +444,19 @@ func (self *Client) parse(buf []byte, f *Frame) error {
444444
return err
445445
}
446446

447+
for i := 0; i+1 < len(f.Fields.TwiData); i += 2 {
448+
twitem := binary.BigEndian.Uint16(f.Fields.TwiData[i : i+2])
449+
select {
450+
case self.TwiChan <- twitem:
451+
default:
452+
self.Log.Errorf("CRITICAL TwiChan is full")
453+
panic("code error mega TwiChan is full")
454+
}
455+
}
456+
447457
switch f.ResponseKind() {
448458
case RESPONSE_TWI_LISTEN:
449459
atomic.AddUint32(&self.stat.TwiListen, 1)
450-
for i := 0; i+1 < len(f.Fields.TwiData); i += 2 {
451-
twitem := binary.BigEndian.Uint16(f.Fields.TwiData[i : i+2])
452-
select {
453-
case self.TwiChan <- twitem:
454-
default:
455-
self.Log.Errorf("CRITICAL TwiChan is full")
456-
panic("code error mega TwiChan is full")
457-
}
458-
}
459460
case RESPONSE_RESET:
460461
atomic.AddUint32(&self.stat.Reset, 1)
461462
if ResetFlag(f.Fields.Mcusr)&ResetFlagWatchdog != 0 {

hardware/mega-firmware/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
mmcu = atmega328p
2-
# mmcu = atmega128
1+
# mmcu = atmega328p
2+
mmcu = atmega168
33

44
avr_gcc = avr-gcc
55
avr_objcopy = avr-objcopy

hardware/mega-firmware/common.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#define LED_CONFIGURED
1313
#endif
1414

15+
uint8_t const RESPONSE_RESERVED_FOR_ERROR = 5;
16+
1517
static packet_t volatile request;
1618
static packet_t volatile response;
1719
static buffer_t volatile debugb;
@@ -40,6 +42,7 @@ static void spi_init_slave(void);
4042
static void spi_step(void);
4143

4244
static void twi_init_slave(uint8_t const address);
45+
static inline void twi_flush_to_response(void);
4346
static void twi_step(void);
4447
static void nop(void) __attribute__((used, always_inline));
4548

@@ -73,9 +76,8 @@ static inline void debugs(char const *const s) {
7376
static inline bool response_empty(void) { return response.h.response == 0; }
7477

7578
static bool response_check_capacity(uint8_t const more) {
76-
uint8_t const RESERVED_FOR_ERROR = 5;
7779
// FIXME length check in buffer_append_n is wasted
78-
if (response.b.length + more + RESERVED_FOR_ERROR >
80+
if (response.b.length + more + RESPONSE_RESERVED_FOR_ERROR >
7981
PACKET_FIELDS_MAX_LENGTH) {
8082
buffer_append((buffer_t *)&response.b, FIELD_ERROR2);
8183
buffer_append_2((buffer_t *)&response.b, ERROR_BUFFER_OVERFLOW, more);

hardware/mega-firmware/config.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#define F_CPU 16000000UL // Clock Speed
55

6-
#define FIRMWARE_VERSION 0x0200
6+
#define FIRMWARE_VERSION 0x0201
77
#define MDB_TIMEOUT_MS 6
88
#define BUFFER_SIZE 50
99

hardware/mega-firmware/main.c

+1-6
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ int main(void) {
112112
nop();
113113

114114
cli();
115-
if (mdb.state != MDB_STATE_IDLE) {
116-
mdb_step();
117-
}
115+
mdb_step();
118116
sei();
119117
nop();
120118

@@ -138,9 +136,6 @@ static void request_exec(void) {
138136
} else if (cmd == COMMAND_DEBUG) {
139137
cmd_debug();
140138
} else if (cmd == COMMAND_FLASH) {
141-
// FIXME simulate bad watchdog event
142-
for (;;)
143-
;
144139
// TODO
145140
response_error2(ERROR_NOT_IMPLEMENTED, 0);
146141
} else if (cmd == COMMAND_MDB_BUS_RESET) {

hardware/mega-firmware/mdb.c

+21-18
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static inline bool uart_send_ready(void) __attribute__((warn_unused_result));
4747
static void mdb_start_receive(void);
4848
static void mdb_finish(mdb_result_t const result, uint8_t const error_data);
4949
static void mdb_bus_reset_finish(void);
50+
static inline void mdb_handle_done(void);
5051
static inline void mdb_handle_recv_end(void);
5152
static inline uint16_t ms_to_timer16_p1024(uint16_t const ms)
5253
__attribute__((const, warn_unused_result));
@@ -76,28 +77,30 @@ static void mdb_step(void) {
7677
mdb_handle_recv_end();
7778
}
7879
if (mdb.state == MDB_STATE_DONE) {
79-
if (!response_empty()) {
80-
return;
81-
}
80+
mdb_handle_done();
81+
}
82+
}
83+
static inline void mdb_handle_done(void) {
84+
if (!response_empty()) {
85+
return;
86+
}
8287

83-
uint8_t const r = mdb.result; // anti-volatile
84-
uint8_t len = mdb_in.length;
88+
uint8_t const r = mdb.result; // anti-volatile
89+
uint8_t len = mdb_in.length;
8590

86-
response_begin(RESPONSE_OK);
87-
response_f2(FIELD_MDB_RESULT, r, mdb.error_data);
88-
response_f2(FIELD_MDB_DURATION10U, (mdb.duration >> 8),
89-
(mdb.duration & 0xff));
91+
response_begin(RESPONSE_OK);
92+
response_f2(FIELD_MDB_RESULT, r, mdb.error_data);
93+
response_f2(FIELD_MDB_DURATION10U, (mdb.duration >> 8),
94+
(mdb.duration & 0xff));
9095

91-
if ((r == MDB_RESULT_SUCCESS) && (len > 0)) {
92-
len--;
93-
}
94-
response_fn(FIELD_MDB_DATA, (uint8_t const *const)mdb_in.data, len);
95-
response.filled = true;
96-
mdb_reset();
97-
return;
96+
if ((r == MDB_RESULT_SUCCESS) && (len > 0)) {
97+
len--;
9898
}
99-
100-
return;
99+
response_fn(FIELD_MDB_DATA, (uint8_t const *const)mdb_in.data, len);
100+
// Convenient place to send TWI_DATA faster than in separate packet.
101+
twi_flush_to_response();
102+
response.filled = true;
103+
mdb_reset();
101104
}
102105
static inline void mdb_handle_recv_end(void) {
103106
uint8_t const len = mdb_in.length;

hardware/mega-firmware/readme.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# What
22

3-
Firmware for MDB adapter. Later called mega because ATMega328p MCU was used.
3+
Firmware for MDB adapter. Later called mega because ATMega MCU was used.
44

55
Usage patterns:
66
- VMC requests: MDB bus reset
@@ -39,6 +39,3 @@ Response (from mega) payload: `response field...`
3939
`field` uses binary tagged encoding, see `protocol.h` `protocol.go`
4040

4141
Frame with `packet.header=RESET` sent by mega on reboot.
42-
43-
44-
# Issues

hardware/mega-firmware/twi.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,22 @@ static void twi_step(void) {
3333
return;
3434
}
3535

36-
// TWI session is finished
37-
if (response_empty()) {
36+
if (response_empty() && (mdb.state == MDB_STATE_IDLE)) {
3837
response_begin(RESPONSE_TWI_LISTEN);
39-
// keyboard sends 1 byte, encode as 2 for future compatibility
4038
response_fn(FIELD_TWI_DATA, (uint8_t const* const)twi_listen.data, length);
39+
buffer_clear_fast((buffer_t * const) & twi_listen);
4140
response.filled = true;
41+
}
42+
}
43+
44+
static inline void twi_flush_to_response(void) {
45+
uint8_t const length = twi_listen.length; // anti-volatile
46+
if (length == 0) {
47+
return;
48+
}
49+
if (response.b.length + length + RESPONSE_RESERVED_FOR_ERROR <
50+
PACKET_FIELDS_MAX_LENGTH) {
51+
response_fn(FIELD_TWI_DATA, (uint8_t const* const)twi_listen.data, length);
4252
buffer_clear_fast((buffer_t * const) & twi_listen);
4353
}
4454
}
@@ -75,6 +85,7 @@ ISR(TWI_vect) {
7585
case TW_SR_GCALL_DATA_ACK:
7686
data = TWDR;
7787
TWCR = TWCR_ACK;
88+
// keyboard sends 1 byte, encode as 2 for future compatibility
7889
buffer_append_2((buffer_t * const) & twi_listen, 0, data);
7990
return;
8091

0 commit comments

Comments
 (0)