Skip to content

Commit

Permalink
Semi-working
Browse files Browse the repository at this point in the history
  • Loading branch information
Akashem06 committed Sep 28, 2024
1 parent 3b6ee48 commit 023332f
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 85 deletions.
4 changes: 2 additions & 2 deletions projects/bootloader/inc/boot_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ typedef enum {

typedef enum { CAN_CONTINUOUS = 0, CAN_ONE_SHOT_MODE, NUM_CAN_MODES } Boot_CanMode;

typedef struct Boot_CanSettings {
typedef struct {
uint16_t device_id;
Boot_CanBitrate bitrate;
bool loopback;
Boot_CanMode mode;
} Boot_CanSettings;

typedef struct Boot_CanMessage {
typedef struct {
uint32_t id;
uint8_t extended;
size_t dlc;
Expand Down
4 changes: 3 additions & 1 deletion projects/bootloader/inc/bootloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ typedef enum {
BOOTLOADER_IDLE,
/// @brief Bootloader is processing a start message
BOOTLOADER_START,
/// @brief Bootloader is waiting for the first byte to be sent (CAN_ARBITRATION_START_FLASH_ID)
/// @brief Bootloader is waiting for the first byte to be sent (CAN_ARBITRATION_SEQUENCING_ID)
BOOTLOADER_DATA_READY,
/// @brief Bootloader is receiving streamed data and flashing it immediately
/// (CAN_ARBITRATION_FLASH_ID)
Expand All @@ -28,6 +28,8 @@ typedef struct {
uintptr_t current_address;
uint32_t bytes_written;
uint32_t binary_size;
uint32_t packet_crc32;
uint16_t expected_sequence_number;
uint16_t buffer_index;

BootloaderStates state;
Expand Down
8 changes: 7 additions & 1 deletion projects/bootloader/inc/bootloader_mcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,11 @@ typedef enum {
/// @brief Bootloader CAN init error
BOOTLOADER_CAN_INIT_ERR,
/// @brief Bootloader attempted to write/read to incorrect address
BOOTLOADER_INVALID_ADDRESS
BOOTLOADER_INVALID_ADDRESS,
/// @brief Bootloader has detected a crc mismatch before writing to flash
BOOTLOADER_CRC_MISMATCH_BEFORE_WRITE,
/// @brief Bootloader has detected a crc mismatch after reading the new flash memory
BOOTLOADER_CRC_MISMATCH_AFTER_WRITE,
/// @brief Bootloader received an incorrect sequence number
BOOTLOADER_SEQUENCE_ERROR
} BootloaderError;
9 changes: 7 additions & 2 deletions projects/bootloader/inc/can_datagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
#define DATA_LEN_SIZE_BYTES 2

#define CAN_ARBITRATION_START_ID 30
#define CAN_ARBITRATION_START_FLASH_ID 31
#define CAN_ARBITRATION_SEQUENCING_ID 31
#define CAN_ARBITRATION_FLASH_ID 32
#define CAN_ARBITRATION_JUMP_ID 33
#define CAN_ARBITRATION_FAULT_ID 34
#define CAN_ARBITRATION_ACK_ID 34

#define CAN_BITRATE 500000

Expand All @@ -29,6 +29,10 @@ typedef struct {
uint16_t node_ids;
uint32_t data_len;
} start;
struct {
uint16_t sequence_num;
uint32_t crc32;
} sequencing;
struct {
uint8_t *binary_data;
} data;
Expand All @@ -42,3 +46,4 @@ typedef struct {
} can_datagram_t;

can_datagram_t unpack_datagram(Boot_CanMessage *msg, uint16_t *target_nodes);
void send_ack_datagram(bool ack, BootloaderError error);
3 changes: 2 additions & 1 deletion projects/bootloader/scripts/bootloader_id.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
START = 30
START_FLASH = 31
SEQUENCING = 31
FLASH = 32
JUMP = 33
ACK = 34

STANDARD_CRC32_POLY = 0x04C11DB7
146 changes: 102 additions & 44 deletions projects/bootloader/scripts/can_datagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from bootloader_id import *

DEFAULT_CHANNEL = 'can0'
CAN_BITRATE = 500000
CAN_BITRATE = 1000000

DATA_SIZE_SIZE = 2
MIN_BYTEARRAY_SIZE = 4
Expand Down Expand Up @@ -183,55 +183,113 @@ def send(self, message, sender_id=0):
print(can_message)
print("Message was sent on {}".format(self.bus.channel_info))

ack_received = False
retry_count = 0
max_retries = 3

while not ack_received and retry_count < max_retries:
try:
ack_msg = self.bus.recv(timeout=5.0)

if ack_msg and ack_msg.arbitration_id == ACK:
if ack_msg.data[0] == 0x01:
ack_received = True
print(f"Received ACK for start message")
elif ack_msg.data[0] == 0x00:
print(f"Received NACK for start message, aborting")
break
else:
print(f"Received unknown response for start message, retrying...")
retry_count += 1
else:
print(f"No ACK/NACK received for start message, retrying...")
retry_count += 1

except can.CanError:
print(f"Error waiting for ACK/NACK for start message, retrying...")
retry_count += 1

if not ack_received:
raise Exception(f"Failed to receive ACK for start message after {max_retries} attempts")


print(f"Start message received succesfully!")

def send_data(self, message, sender_id=0):
'''Send a Datagram over CAN'''
assert isinstance(message, Datagram)

message_extended_arbitration = False
chunk_messages = list(self._chunkify(message.data, 8))
crc32_chunks = list(self._chunkify(message.data, 1024))
sequence_number = 0

for crc_chunk in crc32_chunks:
while chunk_messages:
seq_num_bytes = sequence_number.to_bytes(2, byteorder='little')

# Prepare up to 1024 bytes (128 chunks of 8 bytes each)
current_chunk = chunk_messages[:128]
chunk_messages = chunk_messages[128:]

crc_chunk = b''.join(current_chunk)
crc32_value = crc32.calculate(crc_chunk)
print(crc32_value)
crc_data = crc32_value.to_bytes(4, byteorder='big')
print(crc_data)e

print(crc32_value)

# Create a CAN message for the CRC32 data
# crc_message = can.Message(arbitration_id=CRC32_CHECK,
# data=crc_data,
# is_extended_id=message_extended_arbitration)

message_extended_arbitration = False
can_messages = []

can_messages.append(can.Message(arbitration_id=START_FLASH,
data=chunk_messages[0],
is_extended_id=message_extended_arbitration))

for chunk_message in chunk_messages:
can_messages.append(can.Message(arbitration_id=FLASH,
data=chunk_message,
is_extended_id=message_extended_arbitration))
binary_sent_counter = 0
start_time = time.time()

for msg in can_messages:
try:
# print(msg, "\tBINARY SENT:", binary_sent_counter, "\tTOTAL APP SIZE:", len(message.data))
self.bus.send(msg)
except BaseException:
# print("Bruh")
time.sleep(0.01)
self.bus.send(msg)

end_time = time.time()
elapsed_time = end_time - start_time
print(
"{} messages were sent on {}. Took {}".format(
len(can_messages),
self.bus.channel_info,
elapsed_time))
print(f"CRC32 VALUE: {crc32_value}")
crc_data = crc32_value.to_bytes(4, byteorder='little')

sequencing_data = seq_num_bytes + crc_data

# Send sequence message
sequence_msg = can.Message(arbitration_id=SEQUENCING,
data=sequencing_data,
is_extended_id=message_extended_arbitration)

self.bus.send(sequence_msg)
print(f"Sent sequence message {sequence_number}")

# Send data chunks (up to 1024 bytes)
for chunk in current_chunk:
time.sleep(0.01) # Small delay between messages
data_msg = can.Message(arbitration_id=FLASH,
data=chunk,
is_extended_id=message_extended_arbitration)
self.bus.send(data_msg)

print(f"Sent {len(current_chunk) * 8} bytes for sequence {sequence_number}")

# After sending sequence 0 and its data, start checking for ACK/NACK
if sequence_number > 0 or chunk_messages:
ack_received = False
retry_count = 0
max_retries = 3

while not ack_received and retry_count < max_retries:
try:
ack_msg = self.bus.recv(timeout=5.0)

if ack_msg and ack_msg.arbitration_id == ACK:
if ack_msg.data[0] == 0x01:
ack_received = True
print(f"Received ACK for sequence {sequence_number}")
elif ack_msg.data[0] == 0x00:
print(f"Received NACK for sequence {sequence_number}, retrying...")
retry_count += 1
break
else:
print(f"Received unknown response for sequence {sequence_number}, retrying...")
retry_count += 1
else:
print(f"No ACK/NACK received for sequence {sequence_number}, retrying...")
retry_count += 1

except can.CanError:
print(f"Error waiting for ACK/NACK for sequence {sequence_number}, retrying...")
retry_count += 1

if not ack_received:
raise Exception(f"Failed to receive ACK for sequence {sequence_number} after {max_retries} attempts")

sequence_number += 1

print(f"All data sent successfully. Total sequences: {sequence_number}")

@staticmethod
def _chunkify(data, size):
Expand Down
12 changes: 9 additions & 3 deletions projects/bootloader/scripts/flash_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ def start_flash(self, **kwargs) -> None:
print(f"Starting flash process")
print(f'Sending binary data with size of {self._bin_size}...\n\n')

with open(self._bin_path, 'rb') as bin_data:
bin_content = bytearray(bin_data.read())

remainder = len(bin_content) % 4
if remainder != 0:
padding_size = 4 - remainder
bin_content.extend([0x00] * padding_size)
self._bin_size = os.path.getsize(self._bin_path) + padding_size

start_datagram = Datagram(
datagram_type_id=bootloader_id.START,
node_ids=node_ids,
Expand All @@ -62,9 +71,6 @@ def start_flash(self, **kwargs) -> None:
(self._bin_size >> 24) & 0xff])
)

with open(self._bin_path, 'rb') as bin_data:
bin_content = bytearray(bin_data.read())

flash_datagram = Datagram(
datagram_type_id=bootloader_id.FLASH,
node_ids=node_ids,
Expand Down
Loading

0 comments on commit 023332f

Please sign in to comment.