Skip to content

Commit bc883c3

Browse files
authored
- Fix #169 (#170)
* - Fix #169 - Fix MK4 Y selftest * - Remove trace-events from coverage - Add basic timing test case for AT21CSxx
1 parent 13f1c4e commit bc883c3

File tree

10 files changed

+287
-16
lines changed

10 files changed

+287
-16
lines changed

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
run: cd ${{ runner.workspace }}/MINI404/build && make coverage-html -j4
8080

8181
- name: Strip down Coverage report
82-
run: cd ${{ runner.workspace }}/MINI404/build/meson-logs && lcov -extract coverage.info '*/arm/prusa/*' --rc lcov_branch_coverage=1 --output-file=c2.info && lcov -remove c2.info '*/3rdParty/*' --rc lcov_branch_coverage=1 --output-file=c2.info
82+
run: cd ${{ runner.workspace }}/MINI404/build/meson-logs && lcov -extract coverage.info '*/arm/prusa/*' --rc lcov_branch_coverage=1 --output-file=c2.info && lcov -remove c2.info '*/3rdParty/*' --rc lcov_branch_coverage=1 --output-file=c2.info && lcov -remove c2.info '*trace-events*' --rc lcov_branch_coverage=1 --output-file=c2.info
8383

8484
- name: Upload to codecov.io
8585
uses: codecov/codecov-action@v4

hw/arm/prusa/otp.h

+8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ typedef struct {
2525
MAC_addr mac_address; // MAC address (6 bytes)
2626
uint16_t _padding;
2727
} OTP_v4;
28+
29+
typedef struct {
30+
uint8_t version; // Data structure version (1 bytes)
31+
uint16_t size; // Data structure size (uint16_t little endian)
32+
uint8_t bomID; // BOM ID (1 bytes)
33+
uint32_t timestamp; // UNIX Timestamp from 1970 (uint32_t little endian)
34+
uint8_t datamatrix[24]; // DataMatrix ID 1 (24 bytes)
35+
}OTP_v2 ;
2836
#pragma pack(pop)
2937

3038
#endif

hw/arm/prusa/parts/AT21CSxx.c

+45-14
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "sysemu/block-backend.h"
3333
#include "sysemu/cpu-timers.h"
3434
#include "migration/vmstate.h"
35+
#include "../otp.h"
36+
#include "trace.h"
3537

3638
#define TYPE_AT21CSXX "at21csxx"
3739

@@ -44,7 +46,8 @@
4446
#define AT21_OP_SSM 0xD
4547
#define AT21_OP_HSM 0xE
4648

47-
#define ICOUNT_PER_US 168
49+
// Empirically determined based on the bootloader code and its NOP()s... :-/
50+
#define ICOUNT_PER_US_INITIAL 124
4851

4952
#define DEV_ADDR 0
5053
#define DEV_SIZE 128
@@ -80,11 +83,15 @@ struct AT21CSxxState {
8083

8184
QEMUTimer *line_release;
8285

86+
uint32_t refined_icount;
87+
bool icount_enabled;
88+
8389
int64_t low_start, high_start;
8490
uint8_t bit_counter;
8591
uint8_t byte_in, byte_out;
8692
uint8_t sio_state;
8793

94+
8895
uint8_t byte_count;
8996
uint8_t address_pointer;
9097

@@ -122,6 +129,7 @@ static void at21csxx_line_release(void *opaque)
122129

123130
static bool at21csxx_process_byte(AT21CSxxState *s, uint8_t byte)
124131
{
132+
trace_at21csxx_byte_in(s->byte_count, byte);
125133
switch (s->byte_count)
126134
{
127135
case 0:
@@ -131,6 +139,7 @@ static bool at21csxx_process_byte(AT21CSxxState *s, uint8_t byte)
131139
if (s->cmd.def.read)
132140
{
133141
s->sio_state = SIO_DOUT;
142+
trace_at21csxx_read_mode();
134143
}
135144
switch (s->cmd.def.opcode)
136145
{
@@ -147,39 +156,49 @@ static bool at21csxx_process_byte(AT21CSxxState *s, uint8_t byte)
147156
if (byte < DEV_SIZE)
148157
{
149158
s->address_pointer = byte;
159+
trace_at21csxx_address_set(s->address_pointer);
150160
s->byte_count++;
151161
return true;
152162
}
153163
return false;
154164
default:
165+
trace_at21csxx_data_write(s->address_pointer, byte);
155166
s->data[s->address_pointer++] = byte;
156167
s->address_pointer %= DEV_SIZE;
157168
return true;
158169
}
159170
}
160171

161172
static void at21csxx_sio(void* opaque, int n, int level) {
173+
trace_at21csxx_sio_level(level);
162174
AT21CSxxState *s = AT21CSXX(opaque);
175+
const uint32_t ICOUNT_PER_US = s->icount_enabled ? s->refined_icount : 1000;
163176
if (!level)
164177
{
165-
s->low_start = icount_get_raw();
178+
179+
s->low_start = s->icount_enabled ? icount_get_raw() : qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
166180
int64_t tHigh = s->low_start - s->high_start;
181+
trace_at21csxx_sio_high_icount(tHigh);
167182
if (tHigh > 500 * ICOUNT_PER_US)
168183
{
169-
// printf("AT21 Start cond\n");
184+
trace_at21csxx_start_condition();
170185
s->sio_state = SIO_IDLE;
171186
}
172187
return;
173188
}
174189

175-
s->high_start = icount_get_raw();
190+
s->high_start = s->icount_enabled ? icount_get_raw() : qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
176191

177192
int64_t tLow = s->high_start - s->low_start;
178193

179-
if (tLow > 150 * ICOUNT_PER_US)
194+
trace_at21csxx_sio_low_icount(tLow);
195+
196+
if (tLow >= 150 * ICOUNT_PER_US)
180197
{
181198
s->bit_counter = 0;
182199
s->byte_in = 0;
200+
trace_at21csxx_enter_discovery();
201+
qemu_set_irq(s->irq, 1);
183202
s->sio_state = SIO_DISC;
184203
return;
185204
}
@@ -193,7 +212,7 @@ static void at21csxx_sio(void* opaque, int n, int level) {
193212
{
194213
qemu_irq_lower(s->irq);
195214
timer_mod(s->line_release, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NS_SCALE(6000)); // 2-6 us from the datasheet
196-
// printf("Discovery ack\n");
215+
trace_at21csxx_discovery_ack();
197216
s->sio_state = SIO_IDLE;
198217
}
199218
break;
@@ -208,6 +227,7 @@ static void at21csxx_sio(void* opaque, int n, int level) {
208227
case SIO_DIN:
209228
if (logic_one || logic_zero )
210229
{
230+
trace_at21csxx_bit_logic_val(s->bit_counter, logic_one, logic_zero);
211231
if (s->bit_counter < 8)
212232
{
213233
s->byte_in <<= 1;
@@ -218,12 +238,13 @@ static void at21csxx_sio(void* opaque, int n, int level) {
218238
}
219239
else
220240
{
241+
trace_at21csxx_bit_duration_error(s->bit_counter, tLow);
221242
// printf("w1 Bus unhandled low duration: %"PRId64" instructions\n", tLow);
222243
}
223244
if (s->bit_counter == 8)
224245
{
225246
bool send_ack = at21csxx_process_byte(s, s->byte_in);
226-
// printf("Byte in: %02x - %s\n", s->byte_in, send_ack? "ACK" : "NACK");
247+
//printf("Byte in: %02x - %s\n", s->byte_in, send_ack? "ACK" : "NACK");
227248
s->byte_in = 0;
228249
qemu_set_irq(s->irq, !send_ack);
229250
timer_mod(s->line_release, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NS_SCALE(2000)); // 2-6 us from the datasheet
@@ -238,14 +259,15 @@ static void at21csxx_sio(void* opaque, int n, int level) {
238259
{
239260
case AT21_OP_EEA:
240261
s->byte_out = s->data[s->address_pointer++];
241-
printf("AT21CSxx: Sending byte@ %02x: %02x\n",s->address_pointer-1, s->byte_out);
262+
trace_at21csxx_data_read(s->address_pointer-1, s->byte_out);
242263
break;
243264
default:
244265
printf("AT21 Unhandled read opcode %x\n", s->cmd.def.opcode);
245266
break;
246267
}
247268
/* fallthru */
248269
case 1 ... 7 :
270+
trace_at21csxx_sio_out(s->bit_counter, s->byte_out&0x80);
249271
qemu_set_irq(s->irq, (s->byte_out & 0x80) > 0 );
250272
s->bit_counter++;
251273
s->byte_out <<= 1;
@@ -285,6 +307,12 @@ static void at21csxx_realize(DeviceState *dev, Error **errp)
285307
printf("WARNING: icount is disabled. AT21CSxx EEPROM will NOT WORK!\n");
286308
printf("WARNING: use -icount [number] to enable it.\n");
287309
}
310+
else
311+
{
312+
s->icount_enabled = true;
313+
}
314+
#else
315+
s->icount_enabled = icount_enabled();
288316
#endif
289317
if (s->blk) {
290318

@@ -313,12 +341,14 @@ static void at21csxx_realize(DeviceState *dev, Error **errp)
313341
else
314342
{
315343
// Add some fake data just to avoid 400 re-read attempts during boot... :(
316-
s->data[0] = 0x00;
317-
s->data[1] = 0x20;
318-
s->data[2] = 0x00;
319-
s->data[3] = 0x01;
320-
s->data[8] = '0';
321-
s->data[9] = '0';
344+
OTP_v2* otp = (OTP_v2*) s->data;
345+
otp->version = 2;
346+
otp->size = sizeof(OTP_v2);
347+
otp->bomID = 31; // Last variant that uses table 5... ;)
348+
// Should keep the bootloader happy:
349+
otp->datamatrix[0] = '0';
350+
otp->datamatrix[1] = '0';
351+
322352
}
323353
}
324354

@@ -336,6 +366,7 @@ static void at21csxx_init(Object *obj)
336366

337367
static Property at21csxx_eeprom_props[] = {
338368
DEFINE_PROP_DRIVE("drive", AT21CSxxState, blk),
369+
DEFINE_PROP_UINT32("icount-per-us", AT21CSxxState, refined_icount, ICOUNT_PER_US_INITIAL),
339370
DEFINE_PROP_END_OF_LIST()
340371
};
341372

hw/arm/prusa/parts/tmc2209.c

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "../utility/p404scriptable.h"
3131
#include "../utility/p404_motor_if.h"
3232
#include "../utility/ScriptHost_C.h"
33+
#include "trace.h"
3334

3435
//#define DEBUG_TMC2209 1
3536

@@ -352,6 +353,7 @@ static void tmc2209_read(tmc2209_state *s)
352353
reply[7] = tmc2209_calcCRC(reply,7);
353354
for (int i=0; i<8; i++)
354355
{
356+
trace_tmc2209_byte_out(s->address, reply[i]);
355357
qemu_set_irq(s->byte_out, reply[i]); //
356358
}
357359
}
@@ -363,6 +365,8 @@ static void tmc2209_receive(void *opaque, int n, int level)
363365
s->rx_buffer[s->rx_pos] = (uint8_t)level;
364366
s->rx_pos++;
365367

368+
trace_tmc2209_byte_in(s->address, level);
369+
366370
if (s->rx_pos == 8 && s->rx_buffer[2] & 0x80)
367371
{
368372
if (s->rx_buffer[1] == s->address) tmc2209_write(s);

hw/arm/prusa/parts/trace-events

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
tmc2209_byte_in(uint8_t address, uint8_t byte) "A: %u D: %02x"
2+
tmc2209_byte_out(uint8_t address, uint8_t byte) "A: %u D: %02x"
3+
at21csxx_byte_in(uint8_t ct, uint8_t data) "D@%u: %02x"
4+
at21csxx_byte_out(uint8_t ct, uint8_t data) "D@%u: %02x"
5+
at21csxx_read_mode(void)
6+
at21csxx_address_set(uint8_t address) "A: %02x"
7+
at21csxx_data_write(uint8_t addr, uint8_t data) "write@%u = %02x"
8+
at21csxx_data_read(uint8_t addr, uint8_t data) "read@%u = %02x"
9+
at21csxx_bit_logic_val(uint8_t bit_count, bool logic_1, bool logic_0) "bit %u: 1:%u 0:%u"
10+
at21csxx_bit_duration_error(uint8_t bit_count, uint32_t duration) "Unknown low duration for bit %u: %u"
11+
at21csxx_sio_level(uint8_t level) "SIO: %u"
12+
at21csxx_sio_out(uint8_t bit, bool level) "SIO bit %u: %u"
13+
at21csxx_sio_low_icount(uint32_t icount) "SIO low: %u"
14+
at21csxx_sio_high_icount(uint32_t icount) "SIO high: %u"
15+
at21csxx_start_condition(void)
16+
at21csxx_enter_discovery(void)
17+
at21csxx_discovery_ack(void)

hw/arm/prusa/parts/trace.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "trace/trace-hw_arm_prusa_parts.h"

hw/arm/prusa/prusa-mk4.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ static void mk4_init(MachineState *machine)
591591
qdev_prop_set_string(db2, "indicators", "ZF");
592592

593593
{
594-
int32_t ends[4] = { 100*16*255, 100*16*214, 400*16*(cfg.has_loadcell ? 221: 212),0 };
594+
int32_t ends[4] = { 100*16*255, 100*16*218, 400*16*(cfg.has_loadcell ? 221: 212),0 };
595595
static const char* links[4] = {"motor[0]","motor[1]","motor[2]","motor[3]"};
596596
static int32_t stepsize[4] = { 100*16, 100*16, 400*16, 320*16 };
597597

@@ -891,6 +891,7 @@ static void mk4_init(MachineState *machine)
891891
if (cfg.has_at21) {
892892
dev = qdev_new("at21csxx");
893893
qdev_prop_set_drive(dev, "drive", blk_by_name("loveboard-eeprom"));
894+
object_property_add_child(OBJECT(periphs), "at21csxx", OBJECT(dev));
894895
sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
895896
// 2-way bitbang
896897
// WARNING: F13 is also used by the fan tach gate. So the output gets re-bount below

hw/arm/prusa/stm32_tests/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
qtests_buddy = [
2+
'prusa/stm32_tests/mini404_at21csxx_test',
23
'prusa/stm32_tests/mini404_dwarf_input_test',
34
'prusa/stm32_tests/mini404_encoder_test',
45
'prusa/stm32_tests/mini404_fan_test',

0 commit comments

Comments
 (0)