Index: run.update_package.py =================================================================== diff -u -ra99d0580e0f14cdf80321e963a7121a2225d2c4f -r988824ec54f3d9d4ff92d60d2be09fe8ad09ee29 --- run.update_package.py (.../run.update_package.py) (revision a99d0580e0f14cdf80321e963a7121a2225d2c4f) +++ run.update_package.py (.../run.update_package.py) (revision 988824ec54f3d9d4ff92d60d2be09fe8ad09ee29) @@ -10,22 +10,27 @@ input_arguments_status = True if packages_directory is '': - print("################################ PLEASE PROVIDE A WORKSPACE DIRECTORY ################################") # TODO update + print("################################ PLEASE PROVIDE THE BINARIES #########################################") input_arguments_status = False - # If there is no project is defined (i.e HD, DG), exit + # If there is no project is defined (e.g. TD, DD), exit if sys.argv[2] is None: - print('################################ PLEASE SELECT A PROJECT! ######################################' - '######') # TODO update + print('################################ PLEASE SELECT A STACK ###############################################') input_arguments_status = False + if sys.argv[3] is None: + print('################################ PLEASE SELECT A TARGET ##############################################') + input_arguments_status = False + + if input_arguments_status: stack = sys.argv[2] if sys.argv[2] != '' else None + target = sys.argv[3] if sys.argv[3] != '' else None start = time.time() update = SoftwareUpdateScript() - update.update_software_packages(packages_directory, stack) + update.update_software_packages(packages_directory, stack, target) print('Package Update Time: {:.1f} s'.format(time.time() - start)) Index: scripts/update_package_script/update_package.py =================================================================== diff -u -radea121e63d4eabb225c26bc1efd6741c59e0df3 -r988824ec54f3d9d4ff92d60d2be09fe8ad09ee29 --- scripts/update_package_script/update_package.py (.../update_package.py) (revision adea121e63d4eabb225c26bc1efd6741c59e0df3) +++ scripts/update_package_script/update_package.py (.../update_package.py) (revision 988824ec54f3d9d4ff92d60d2be09fe8ad09ee29) @@ -1,7 +1,7 @@ import os import math -from scripts.update_package_script.utilities import Utilities, SWUpdateCommands, CanCommStatus, SWUpdateTargets +from scripts.update_package_script.utilities import Utilities, SWUpdateCommands, CanCommStatus, UpdateStacks, UpdateStacksTargets class SoftwareUpdateScript: """ @@ -11,6 +11,7 @@ """ _SW_UPDATE_PAYLOAD_BYTES = 256 _SW_UPDATE_STACK = 'stack_name' + _SW_UPDATE_TARGET = 'stack_target' _BINARY_FILE_SIZE = 'file_size' _WRITTEN_BYTE_COUNT = 'byte_count' _WRITE_COUNTER = 'write_counter' @@ -30,34 +31,45 @@ @return none """ self._sw_update_status[self._SW_UPDATE_STACK] = 0 + self._sw_update_status[self._SW_UPDATE_TARGET] = 0 self._sw_update_status[self._BINARY_FILE_SIZE] = 0 self._sw_update_status[self._WRITTEN_BYTE_COUNT] = 0 self._sw_update_status[self._WRITE_COUNTER] = 0 self._utilities.clear_msg_ack_nack_status(self._utilities.SEND_MSG_ACK_STATUS_KEY_NAME) self._utilities.clear_msg_ack_nack_status(self._utilities.UPDATE_MSG_ACK_STATUS_KEY_NAME) - def _prepare_for_sw_update(self, stack_to_update: str, file_path: str): + def _prepare_for_sw_update(self, stack_to_update: str, destination: str, file_path: str): """ Privately accessible method to prepare for software update. @param stack_to_update: The stack to update its software (TD, DD) + @param destination: The update destination (Firmware, FPGA) @param file_path: The file location of the binary file @return True if prepare was successful otherwise, False """ status = False self._reset_variables() # TODO how to read from a manifest file. Right now it is passed directly - stack_to_update = 'TARGET_' + stack_to_update.upper() - self._sw_update_status[self._SW_UPDATE_STACK] = SWUpdateTargets[stack_to_update].value + # TODO if stack to update and stack target are not provided, then just read through the manifest files + if stack_to_update is not None and destination is not None: + stack_to_update = stack_to_update.upper() + destination = destination.upper() + if stack_to_update in UpdateStacks.__members__: self._sw_update_status[self._SW_UPDATE_STACK] = UpdateStacks[stack_to_update].value + if destination in UpdateStacksTargets.__members__: self._sw_update_status[self._SW_UPDATE_TARGET] = UpdateStacksTargets[destination].value + + # TODo manifest + #self._sw_update_status[self._SW_UPDATE_STACK] = stack_to_update + #self._sw_update_status[self._SW_UPDATE_TARGET] = stack_target self._sw_update_status[self._BINARY_FILE_SIZE] = os.path.getsize(file_path) send_ack_status = self._utilities.get_msg_ack_nack_status(self._utilities.SEND_MSG_ACK_STATUS_KEY_NAME) # If the communication has not started, send the command start for update if send_ack_status == CanCommStatus.CAN_COMM_NOT_STARTED.value: self._utilities.send_command_msg(SWUpdateCommands.SW_UPDATE_START.value, - self._sw_update_status[self._SW_UPDATE_STACK]) + self._sw_update_status[self._SW_UPDATE_STACK], + self._sw_update_status[self._SW_UPDATE_TARGET]) send_ack_status = self._utilities.get_msg_ack_nack_status(self._utilities.SEND_MSG_ACK_STATUS_KEY_NAME) # Once the CAN communication was ready it means the command went through successfully, and it is ready for the next command. if send_ack_status == CanCommStatus.CAN_COMM_READY.value: status = True @@ -76,7 +88,7 @@ write_counter = self._sw_update_status[self._WRITE_COUNTER] binary_file_size_bytes = self._sw_update_status[self._BINARY_FILE_SIZE] target_stack = self._sw_update_status[self._SW_UPDATE_STACK] - target_stack =SWUpdateTargets(target_stack).name + target_stack =UpdateStacksTargets(target_stack).name bytes_written = self._sw_update_status[self._WRITTEN_BYTE_COUNT] # Get number of payloads needed to update the binary but since this is for display only, it is scaled down 10 times num_of_payloads_needed = math.ceil(binary_file_size_bytes / (self._SW_UPDATE_PAYLOAD_BYTES * progress_bar_scale)) @@ -126,20 +138,22 @@ if line == b'': # Read line was b'' meaning the binary file was read completely, send the verification command to the bootloader self._utilities.send_command_msg(SWUpdateCommands.SW_UPDATE_VERIFY.value, - self._sw_update_status[self._SW_UPDATE_STACK]) + self._sw_update_status[self._SW_UPDATE_STACK], + self._sw_update_status[self._SW_UPDATE_TARGET]) print("Leave file") break - if line == b'': print("Leave file 2"); break # TODO remove thi line + if line == b'': print("Leave file 2"); break # TODO remove this line # Close the binary file f.close() - def update_software_packages(self, packages_dir: str, stack_to_update: str = None): + def update_software_packages(self, packages_dir: str, stack_to_update: str = None, stack_target: str = None): """ Publicly accessible method to update the software packages (firmware and FPGA) @param packages_dir: The address of the binary file - @param stack_to_update: If the user wants to provide an individual stack (e.g. dd) + @param stack_to_update: If the user wants to provide an individual stack (TD, DD) + @param stack_target: If the user wants to provide an individual target (Firmware, FPGA) @return none """ @@ -152,6 +166,6 @@ if not file.endswith(".bin"): continue path = os.path.join(packages_dir, file) - if self._prepare_for_sw_update(stack_to_update, path): + if self._prepare_for_sw_update(stack_to_update, stack_target, path): self._process_binary_file(path) Index: scripts/update_package_script/utilities.py =================================================================== diff -u -radea121e63d4eabb225c26bc1efd6741c59e0df3 -r988824ec54f3d9d4ff92d60d2be09fe8ad09ee29 --- scripts/update_package_script/utilities.py (.../utilities.py) (revision adea121e63d4eabb225c26bc1efd6741c59e0df3) +++ scripts/update_package_script/utilities.py (.../utilities.py) (revision 988824ec54f3d9d4ff92d60d2be09fe8ad09ee29) @@ -15,8 +15,7 @@ class SWUpdateCommands(SWUpdateEnum): SW_UPDATE_START = 0 SW_UPDATE_ABORT = 1 - SW_UPDATE_RUN_APP = 2 - SW_UPDATE_VERIFY = 3 + SW_UPDATE_VERIFY = 2 NUM_OF_SW_UPDATE_CMDS = 4 @unique @@ -30,13 +29,17 @@ NUM_OF_CAN_COMM_STATES = 6 @unique -class SWUpdateTargets(SWUpdateEnum): - TARGET_TD = 0 - TARGET_TD_FPGA = 1 - TARGET_DD = 2 - TARGET_DD_FPGA = 3 - NUM_OF_TARGETS = 4 +class UpdateStacks(SWUpdateEnum): + STACK_TD = 0 + STACK_DD = 1 + NUM_OF_STACKS = 2 +@unique +class UpdateStacksTargets(SWUpdateEnum): + TARGET_FIRMWARE = 0 + TARGET_FPGA = 1 + NUM_OF_TARGETS = 2 + class Utilities: """ Software update utilities class @@ -84,16 +87,18 @@ _NUM_OF_BYTES_PER_CAN_FRAME = 8 _CAN_INTERFACE = 'can0' _SEND_CMD_MAIL_BOX = 0x601 - _RESP_CMD_MAIL_BOX = '0x602' _CAN_MSG_WAIT_FOR_RESP_S = 3.0 _RESP_MSG_ACK = 1 _RESP_MSG_NACK = 0 _RESP_MSG_ID_INDEX = 0 - _RESP_ACK_NACK_INDEX = 1 + _RESP_ACK_NACK_INDEX = 2 _RESP_CRC_START_INDEX = 4 SEND_MSG_ACK_STATUS_KEY_NAME = 'cmd' UPDATE_MSG_ACK_STATUS_KEY_NAME = 'update' + _STACK_SEND_UPDATE_MAIL_BOX = 'send' + _STACK_RCV_RESP_MAIL_BOX = 'receive' + def __init__(self): """ Utilities class constructor @@ -102,15 +107,17 @@ self._can_bus = SocketcanBus(channel=self._CAN_INTERFACE) self._msg_id_count = 0 self._msg_sw_update_index = 0 - self._update_mail_boxes = self._prepare_update_mail_boxes() + self._update_mail_boxes = dict() self._msg_ack_nack_status = dict() self._total_msg_count = 0 + self._stack = 0 self._msg_ack_nack_status[self.SEND_MSG_ACK_STATUS_KEY_NAME] = CanCommStatus.CAN_COMM_NOT_STARTED.value self._msg_ack_nack_status[self.UPDATE_MSG_ACK_STATUS_KEY_NAME] = CanCommStatus.CAN_COMM_NOT_STARTED.value - self.file_handle = open(os.path.join(os.getcwd(), 'ack_log.log'), 'w') + self._prepare_update_mail_boxes(self._update_mail_boxes) + def get_msg_ack_nack_status(self, msg_type: str): """ Publicly accessible method to get the ack or nack status of a message @@ -131,12 +138,13 @@ """ self._msg_ack_nack_status[msg_type] = CanCommStatus.CAN_COMM_NOT_STARTED.value - def send_command_msg(self, cmd: int, target: int): + def send_command_msg(self, cmd: int, stack: int, destination: int): """ Publicly accessible method to send a command message to the bootloader @param cmd: The command to send (e.g. update, verify) - @param target: The target stack (TD, DD) + @param stack: The stack (TD, DD) + @param target: The destination (Firmware, FPGA) @return none """ @@ -145,18 +153,19 @@ # 1 byte with command a nibble and target as a nibble # 2 bytes as random value for cybersecurity. It is 0 now. # 4 bytes as message CRC - self._msg_id_count = self._msg_id_count + 1 if self._msg_id_count < 0xFF else 0 - can_msg_bytes = self._convert_data_to_bytes('