Skip to content

Commit 536b8de

Browse files
committed
Add error handling to binary programming.
1 parent e29fc4c commit 536b8de

File tree

3 files changed

+113
-85
lines changed

3 files changed

+113
-85
lines changed

prawnblaster/fast_serial.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ uint32_t fast_serial_read(const char * buffer, uint32_t buffer_size){
3535
// Read bytes until terminator reached (blocks until terminator or buffer_size is reached)
3636
uint32_t fast_serial_read_until(char * buffer, uint32_t buffer_size, char until){
3737
uint32_t buffer_idx = 0;
38-
while(buffer_idx < buffer_size){
38+
while(buffer_idx < buffer_size - 1){
3939
while(fast_serial_read_available() > 0){
4040
int32_t next_char = tud_cdc_read_char();
4141

@@ -51,6 +51,7 @@ uint32_t fast_serial_read_until(char * buffer, uint32_t buffer_size, char until)
5151
}
5252
fast_serial_task();
5353
}
54+
buffer[buffer_idx] = '\0'; // Null terminate string
5455
return buffer_idx;
5556
}
5657

prawnblaster/fast_serial.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static inline uint32_t fast_serial_read_atomic(char * buffer, uint32_t buffer_si
4646
uint32_t fast_serial_read(const char * buffer, uint32_t buffer_size);
4747

4848
// Read bytes until terminator reached (blocks until terminator or buffer_size is reached)
49+
// Adds null terminator to buffer after read completes (reserving one byte in buffer for this)
4950
uint32_t fast_serial_read_until(char * buffer, uint32_t buffer_size, char until);
5051

5152
// Clear read FIFO (without reading it)

prawnblaster/prawnblaster.cpp

Lines changed: 110 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ void resus_callback(void)
713713

714714
void loop()
715715
{
716-
fast_serial_read_until(readstring, 256, '\n');
716+
fast_serial_read_until(readstring, 256, '\n');
717717
int local_status = get_status();
718718
if (strncmp(readstring, "version", 7) == 0)
719719
{
@@ -1152,7 +1152,7 @@ void loop()
11521152
}
11531153
else if (strncmp(readstring, "setb ", 5) == 0)
11541154
{
1155-
// set a large block of instructions encoded in a binary blob of fixed length.
1155+
// set a large block of instructions encoded in a binary blob of fixed length.
11561156
unsigned int start_addr;
11571157
unsigned int inst_count;
11581158
unsigned int pseudoclock;
@@ -1166,115 +1166,141 @@ void loop()
11661166
{
11671167
fast_serial_printf("The specified pseudoclock must be between 0 and 3 (inclusive)\r\n");
11681168
}
1169-
else if (start_addr >= max_instructions || start_addr + inst_count >= max_instructions)
1169+
else if (start_addr + inst_count >= max_instructions)
11701170
{
1171-
fast_serial_printf("invalid address or too many instructions\r\n");
1171+
fast_serial_printf("Invalid address and/or too many instructions (%d + %d).\r\n", start_addr, inst_count);
11721172
}
1173-
// It takes 8 bytes to describe an instruction: 4 bytes for reps, 4 bytes for half period
1174-
uint32_t inst_per_buffer = SERIAL_BUFFER_SIZE / 8;
1175-
unsigned int addr = start_addr;
1176-
while(inst_count > inst_per_buffer){
1177-
fast_serial_read(readstring, 8*inst_per_buffer);
1178-
for (int i = 0; i < inst_per_buffer; i++)
1179-
{
1180-
uint32_t reps = ((readstring[8*i + 7] << 24)
1181-
| (readstring[8*i + 6] << 16)
1182-
| (readstring[8*i + 5] << 8)
1183-
| (readstring[8*i + 4]));
1184-
uint32_t half_period = ((readstring[8*i + 3] << 24)
1185-
| (readstring[8*i + 2] << 16)
1186-
| (readstring[8*i + 1] << 8)
1187-
| (readstring[8*i + 0]));
1188-
1189-
if (reps == 0)
1173+
else
1174+
{
1175+
fast_serial_printf("ready\r\n");
1176+
// It takes 8 bytes to describe an instruction: 4 bytes for reps, 4 bytes for half period
1177+
uint32_t inst_per_buffer = SERIAL_BUFFER_SIZE / 8;
1178+
unsigned int addr = start_addr;
1179+
1180+
// Variables to track errors
1181+
uint32_t reps_error_count = 0;
1182+
uint32_t last_reps_error_idx = 0;
1183+
uint32_t half_period_error_count = 0;
1184+
uint32_t last_half_period_error_idx = 0;
1185+
1186+
while(inst_count > inst_per_buffer){
1187+
fast_serial_read(readstring, 8*inst_per_buffer);
1188+
for (int i = 0; i < inst_per_buffer; i++)
11901189
{
1191-
// This indicates either a stop or a wait instruction
1192-
instructions[address_offset + addr * 2] = 0;
1193-
if (half_period == 0)
1190+
uint32_t reps = ((readstring[8*i + 7] << 24)
1191+
| (readstring[8*i + 6] << 16)
1192+
| (readstring[8*i + 5] << 8)
1193+
| (readstring[8*i + 4]));
1194+
uint32_t half_period = ((readstring[8*i + 3] << 24)
1195+
| (readstring[8*i + 2] << 16)
1196+
| (readstring[8*i + 1] << 8)
1197+
| (readstring[8*i + 0]));
1198+
1199+
if (reps == 0)
11941200
{
1195-
// It's a stop instruction
1196-
instructions[address_offset + addr * 2 + 1] = 0;
1197-
addr++;
1201+
// This indicates either a stop or a wait instruction
1202+
instructions[address_offset + addr * 2] = 0;
1203+
if (half_period == 0)
1204+
{
1205+
// It's a stop instruction
1206+
instructions[address_offset + addr * 2 + 1] = 0;
1207+
addr++;
1208+
}
1209+
else if (half_period >= 6)
1210+
{
1211+
// It's a wait instruction. See "set" command for why we do this.
1212+
instructions[address_offset + addr * 2 + 1] = (half_period - 4) / 2;
1213+
addr++;
1214+
}
1215+
else
1216+
{
1217+
reps_error_count++;
1218+
last_reps_error_idx = (address_offset + addr * 2 + 1) / 2;
1219+
}
11981220
}
1199-
else if (half_period >= 6)
1221+
else if (half_period < (non_loop_path_length))
12001222
{
1201-
// It's a wait instruction. See "set" command for why we do this.
1202-
instructions[address_offset + addr * 2 + 1] = (half_period - 4) / 2;
1203-
addr++;
1223+
fast_serial_printf("half-period too short\r\n");
1224+
half_period_error_count++;
1225+
last_half_period_error_idx = (address_offset + addr * 2 + 1) / 2;
12041226
}
12051227
else
12061228
{
1207-
fast_serial_printf("invalid request\r\n");
1229+
instructions[address_offset + addr * 2] = reps;
1230+
instructions[address_offset + addr * 2 + 1] = half_period - non_loop_path_length;
1231+
addr++;
12081232
}
12091233
}
1210-
else if (half_period < (non_loop_path_length))
1211-
{
1212-
fast_serial_printf("half-period too short\r\n");
1213-
}
1214-
else if (reps < 1)
1215-
{
1216-
fast_serial_printf("reps must be at least one\r\n");
1217-
}
1218-
else
1219-
{
1220-
instructions[address_offset + addr * 2] = reps;
1221-
instructions[address_offset + addr * 2 + 1] = half_period - non_loop_path_length;
1222-
addr++;
1223-
}
1234+
inst_count -= inst_per_buffer;
12241235
}
1225-
inst_count -= inst_per_buffer;
1226-
}
1227-
// In this if statement, we read a final serial buffer and load it into instructions.
1228-
if(inst_count > 0){
1229-
fast_serial_read(readstring, 8*inst_count);
1230-
for(int i = 0; i < inst_count; i++){
1231-
uint32_t reps = ((readstring[8*i + 7] << 24)
1232-
| (readstring[8*i + 6] << 16)
1233-
| (readstring[8*i + 5] << 8)
1234-
| (readstring[8*i + 4]));
1235-
uint32_t half_period = ((readstring[8*i + 3] << 24)
1236-
| (readstring[8*i + 2] << 16)
1237-
| (readstring[8*i + 1] << 8)
1238-
| (readstring[8*i + 0]));
1239-
1240-
if (reps == 0)
1236+
// In this if statement, we read a final serial buffer and load it into instructions.
1237+
if(inst_count > 0)
1238+
{
1239+
fast_serial_read(readstring, 8*inst_count);
1240+
for(int i = 0; i < inst_count; i++)
12411241
{
1242-
// This indicates either a stop or a wait instruction
1243-
instructions[address_offset + addr * 2] = 0;
1244-
if (half_period == 0)
1242+
uint32_t reps = ((readstring[8*i + 7] << 24)
1243+
| (readstring[8*i + 6] << 16)
1244+
| (readstring[8*i + 5] << 8)
1245+
| (readstring[8*i + 4]));
1246+
uint32_t half_period = ((readstring[8*i + 3] << 24)
1247+
| (readstring[8*i + 2] << 16)
1248+
| (readstring[8*i + 1] << 8)
1249+
| (readstring[8*i + 0]));
1250+
1251+
if (reps == 0)
12451252
{
1246-
// It's a stop instruction
1247-
instructions[address_offset + addr * 2 + 1] = 0;
1248-
addr++;
1253+
// This indicates either a stop or a wait instruction
1254+
instructions[address_offset + addr * 2] = 0;
1255+
if (half_period == 0)
1256+
{
1257+
// It's a stop instruction
1258+
instructions[address_offset + addr * 2 + 1] = 0;
1259+
addr++;
1260+
}
1261+
else if (half_period >= 6)
1262+
{
1263+
// It's a wait instruction. See "set" command for why we do this.
1264+
instructions[address_offset + addr * 2 + 1] = (half_period - 4) / 2;
1265+
addr++;
1266+
}
1267+
else
1268+
{
1269+
reps_error_count++;
1270+
last_reps_error_idx = (address_offset + addr * 2 + 1) / 2;
1271+
}
12491272
}
1250-
else if (half_period >= 6)
1273+
else if (half_period < (non_loop_path_length))
12511274
{
1252-
// It's a wait instruction. See "set" command for why we do this.
1253-
instructions[address_offset + addr * 2 + 1] = (half_period - 4) / 2;
1254-
addr++;
1275+
half_period_error_count++;
1276+
last_half_period_error_idx = (address_offset + addr * 2 + 1) / 2;
1277+
fast_serial_printf("half-period too short\r\n");
12551278
}
12561279
else
12571280
{
1258-
fast_serial_printf("invalid request\r\n");
1281+
instructions[address_offset + addr * 2] = reps;
1282+
instructions[address_offset + addr * 2 + 1] = half_period - non_loop_path_length;
1283+
addr++;
12591284
}
12601285
}
1261-
else if (half_period < (non_loop_path_length))
1262-
{
1263-
fast_serial_printf("half-period too short\r\n");
1264-
}
1265-
else if (reps < 1)
1286+
}
1287+
if (reps_error_count == 0 && half_period_error_count == 0)
1288+
{
1289+
fast_serial_printf("ok\r\n");
1290+
}
1291+
else
1292+
{
1293+
if (reps_error_count > 0)
12661294
{
1267-
fast_serial_printf("reps must be at least one\r\n");
1295+
fast_serial_printf("Invalid half-period for wait in %d instructions, most recent error at instruction %d. Skipping these instructions.\r\n", reps_error_count, last_reps_error_idx);
12681296
}
1269-
else
1297+
if (reps_error_count > 0)
12701298
{
1271-
instructions[address_offset + addr * 2] = reps;
1272-
instructions[address_offset + addr * 2 + 1] = half_period - non_loop_path_length;
1273-
addr++;
1299+
fast_serial_printf("Too short half-period in %d instructions, most recent error at instruction %d. Skipping these instructions.\r\n", half_period_error_count, last_half_period_error_idx);
1300+
12741301
}
12751302
}
12761303
}
1277-
fast_serial_printf("ok\r\n");
12781304
}
12791305
else if (strncmp(readstring, "go high", 7) == 0)
12801306
{

0 commit comments

Comments
 (0)