[FL-1443, FL-1289] Move assets compilation to separate Makefile. Add scripts folder. Add OTP flashing with DFU. (#531)
* Assets: move assets compilation to separate Makefile. Move all scripts to scripts folder. Add scripts ReadMe. Add precompiled assets. * Split assets.py into separate entities. Option bytes for FL-1289 and checker/setter. * Cli: explicitly initialize variable befor use in api_hal_vcp_rx_with_timeout * Rename ob_check script to ob.
This commit is contained in:
		
							parent
							
								
									359bbdfe69
								
							
						
					
					
						commit
						8116bfcbab
					
				| @ -51,7 +51,7 @@ size_t cli_read(Cli* cli, uint8_t* buffer, size_t size) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool cli_cmd_interrupt_received(Cli* cli) { | bool cli_cmd_interrupt_received(Cli* cli) { | ||||||
|     char c; |     char c = '\0'; | ||||||
|     api_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 1); |     api_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 1); | ||||||
|     return c == CliSymbolAsciiETX; |     return c == CliSymbolAsciiETX; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								assets/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								assets/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | PROJECT_ROOT		= $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST))))..) | ||||||
|  | 
 | ||||||
|  | include				$(PROJECT_ROOT)/assets/assets.mk | ||||||
|  | 
 | ||||||
|  | $(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILLER) | ||||||
|  | 	@echo "\tASSETS\t" $@ | ||||||
|  | 	@$(ASSETS_COMPILLER) icons -s $(ASSETS_SOURCE_DIR) -o $(ASSETS_COMPILED_DIR) | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	@echo "\tCLEAN\t" | ||||||
|  | 	@$(RM) $(ASSETS) | ||||||
| @ -1,3 +1,13 @@ | |||||||
|  | # Requirements | ||||||
|  | 
 | ||||||
|  | - Python3 | ||||||
|  | - ImageMagic | ||||||
|  | - Make | ||||||
|  | 
 | ||||||
|  | # Compiling | ||||||
|  | 
 | ||||||
|  | 	make all | ||||||
|  | 
 | ||||||
| # Asset naming rules | # Asset naming rules | ||||||
| 
 | 
 | ||||||
| ## Images and Animations | ## Images and Animations | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| ASSETS_DIR			:= $(PROJECT_ROOT)/assets | ASSETS_DIR			:= $(PROJECT_ROOT)/assets | ||||||
| ASSETS_COMPILLER	:= $(ASSETS_DIR)/assets.py | ASSETS_COMPILLER	:= $(PROJECT_ROOT)/scripts/assets.py | ||||||
| ASSETS_OUTPUT_DIR	:= $(ASSETS_DIR)/output | ASSETS_COMPILED_DIR	:= $(ASSETS_DIR)/compiled | ||||||
| ASSETS_SOURCE_DIR	:= $(ASSETS_DIR)/icons | ASSETS_SOURCE_DIR	:= $(ASSETS_DIR)/icons | ||||||
| 
 | 
 | ||||||
| ASSETS_SOURCES		+= $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') | ASSETS_SOURCES		+= $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') | ||||||
| ASSETS				+= $(ASSETS_OUTPUT_DIR)/assets_icons.c | ASSETS				+= $(ASSETS_COMPILED_DIR)/assets_icons.c | ||||||
| 
 | 
 | ||||||
| CFLAGS				+= -I$(ASSETS_OUTPUT_DIR) | CFLAGS				+= -I$(ASSETS_COMPILED_DIR) | ||||||
| C_SOURCES			+= $(ASSETS_OUTPUT_DIR)/assets_icons.c | C_SOURCES			+= $(ASSETS_COMPILED_DIR)/assets_icons.c | ||||||
|  | |||||||
							
								
								
									
										617
									
								
								assets/compiled/assets_icons.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										617
									
								
								assets/compiled/assets_icons.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										131
									
								
								assets/compiled/assets_icons.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								assets/compiled/assets_icons.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <gui/icon.h> | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  | 	I_SDQuestion_35x43, | ||||||
|  | 	I_SDError_43x35, | ||||||
|  | 	I_Health_16x16, | ||||||
|  | 	I_FaceCharging_29x14, | ||||||
|  | 	I_BatteryBody_52x28, | ||||||
|  | 	I_Voltage_16x16, | ||||||
|  | 	I_Temperature_16x16, | ||||||
|  | 	I_FaceNopower_29x14, | ||||||
|  | 	I_FaceNormal_29x14, | ||||||
|  | 	I_Battery_16x16, | ||||||
|  | 	I_FaceConfused_29x14, | ||||||
|  | 	I_PassportBottom_128x17, | ||||||
|  | 	I_DoorLeft_8x56, | ||||||
|  | 	I_DoorLocked_10x56, | ||||||
|  | 	I_DoorRight_8x56, | ||||||
|  | 	I_DoorLeft_70x55, | ||||||
|  | 	I_PassportLeft_6x47, | ||||||
|  | 	I_DoorRight_70x55, | ||||||
|  | 	I_LockPopup_100x49, | ||||||
|  | 	I_WalkR2_32x32, | ||||||
|  | 	I_WalkL2_32x32, | ||||||
|  | 	I_WalkRB1_32x32, | ||||||
|  | 	I_Home_painting_17x20, | ||||||
|  | 	I_WalkLB2_32x32, | ||||||
|  | 	I_Sofa_40x13, | ||||||
|  | 	I_WalkLB1_32x32, | ||||||
|  | 	I_PC_22x29, | ||||||
|  | 	I_WalkL1_32x32, | ||||||
|  | 	I_TV_20x20, | ||||||
|  | 	I_WalkR1_32x32, | ||||||
|  | 	I_WalkRB2_32x32, | ||||||
|  | 	I_TV_20x24, | ||||||
|  | 	I_dir_10px, | ||||||
|  | 	I_Nfc_10px, | ||||||
|  | 	I_sub1_10px, | ||||||
|  | 	I_ir_10px, | ||||||
|  | 	I_ibutt_10px, | ||||||
|  | 	I_unknown_10px, | ||||||
|  | 	I_ble_10px, | ||||||
|  | 	I_125_10px, | ||||||
|  | 	I_FX_SittingB_40x27, | ||||||
|  | 	I_BigGames_24x24, | ||||||
|  | 	I_BigProfile_24x24, | ||||||
|  | 	I_DolphinOkay_41x43, | ||||||
|  | 	I_DolphinFirstStart5_45x53, | ||||||
|  | 	I_DolphinFirstStart4_67x53, | ||||||
|  | 	I_DolphinFirstStart2_59x51, | ||||||
|  | 	I_DolphinFirstStart0_70x53, | ||||||
|  | 	I_DolphinFirstStart6_58x54, | ||||||
|  | 	I_DolphinFirstStart1_59x53, | ||||||
|  | 	I_DolphinFirstStart8_56x51, | ||||||
|  | 	I_DolphinFirstStart7_61x51, | ||||||
|  | 	I_Flipper_young_80x60, | ||||||
|  | 	I_BigBurger_24x24, | ||||||
|  | 	I_FX_Bang_32x6, | ||||||
|  | 	I_DolphinFirstStart3_57x48, | ||||||
|  | 	I_BadUsb_9x8, | ||||||
|  | 	I_PlaceholderR_30x13, | ||||||
|  | 	I_Background_128x8, | ||||||
|  | 	I_Lock_8x8, | ||||||
|  | 	I_Battery_26x8, | ||||||
|  | 	I_PlaceholderL_11x13, | ||||||
|  | 	I_Battery_19x8, | ||||||
|  | 	I_SDcardMounted_11x8, | ||||||
|  | 	I_SDcardFail_11x8, | ||||||
|  | 	I_USBConnected_15x8, | ||||||
|  | 	I_Bluetooth_5x8, | ||||||
|  | 	I_Background_128x11, | ||||||
|  | 	I_IrdaArrowUp_4x8, | ||||||
|  | 	I_IrdaLearnShort_128x31, | ||||||
|  | 	I_IrdaArrowDown_4x8, | ||||||
|  | 	I_IrdaLearn_128x64, | ||||||
|  | 	I_IrdaSend_128x64, | ||||||
|  | 	I_IrdaSendShort_128x34, | ||||||
|  | 	I_passport_happy1_43x45, | ||||||
|  | 	I_passport_bad3_43x45, | ||||||
|  | 	I_passport_okay2_43x45, | ||||||
|  | 	I_passport_bad2_43x45, | ||||||
|  | 	I_passport_okay3_43x45, | ||||||
|  | 	I_passport_bad1_43x45, | ||||||
|  | 	I_passport_happy3_43x45, | ||||||
|  | 	I_passport_happy2_43x45, | ||||||
|  | 	I_passport_okay1_43x45, | ||||||
|  | 	I_ButtonRightSmall_3x5, | ||||||
|  | 	I_ButtonLeft_4x7, | ||||||
|  | 	I_ButtonLeftSmall_3x5, | ||||||
|  | 	I_ButtonRight_4x7, | ||||||
|  | 	I_ButtonCenter_7x7, | ||||||
|  | 	A_Games_14, | ||||||
|  | 	A_Plugins_14, | ||||||
|  | 	A_Passport_14, | ||||||
|  | 	A_Sub1ghz_14, | ||||||
|  | 	A_NFC_14, | ||||||
|  | 	A_Tamagotchi_14, | ||||||
|  | 	A_FileManager_14, | ||||||
|  | 	A_125khz_14, | ||||||
|  | 	A_U2F_14, | ||||||
|  | 	A_Infrared_14, | ||||||
|  | 	A_Power_14, | ||||||
|  | 	A_Settings_14, | ||||||
|  | 	A_iButton_14, | ||||||
|  | 	A_Bluetooth_14, | ||||||
|  | 	A_GPIO_14, | ||||||
|  | 	I_DolphinMafia_115x62, | ||||||
|  | 	I_DolphinExcited_64x63, | ||||||
|  | 	I_iButtonDolphinSuccess_109x60, | ||||||
|  | 	I_iButtonDolphinVerySuccess_108x52, | ||||||
|  | 	I_iButtonKey_49x44, | ||||||
|  | 	I_DolphinNice_96x59, | ||||||
|  | 	I_DolphinWait_61x59, | ||||||
|  | 	A_Wink_128x64, | ||||||
|  | 	A_MDWL_32x32, | ||||||
|  | 	A_MDWR_32x32, | ||||||
|  | 	A_WatchingTV_128x64, | ||||||
|  | 	A_MDI_32x32, | ||||||
|  | 	A_MDWRB_32x32, | ||||||
|  | 	A_MDIB_32x32, | ||||||
|  | 	A_FX_Sitting_40x27, | ||||||
|  | 	A_MDWLB_32x32, | ||||||
|  | 	I_KeySave_24x11, | ||||||
|  | 	I_KeyBackspaceSelected_16x9, | ||||||
|  | 	I_KeySaveSelected_24x11, | ||||||
|  | 	I_KeyBackspace_16x9, | ||||||
|  | } IconName; | ||||||
|  | 
 | ||||||
|  | Icon * assets_icons_get(IconName name); | ||||||
							
								
								
									
										5
									
								
								assets/compiled/assets_icons_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								assets/compiled/assets_icons_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <assets_icons.h> | ||||||
|  | 
 | ||||||
|  | const IconData * assets_icons_get_data(IconName name); | ||||||
							
								
								
									
										1
									
								
								assets/output/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								assets/output/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +0,0 @@ | |||||||
| * |  | ||||||
| @ -8,7 +8,7 @@ ASM_SOURCES		+= $(wildcard src/*.s) | |||||||
| C_SOURCES		+= $(wildcard src/*.c) | C_SOURCES		+= $(wildcard src/*.c) | ||||||
| CPP_SOURCES		+= $(wildcard src/*.cpp) | CPP_SOURCES		+= $(wildcard src/*.cpp) | ||||||
| 
 | 
 | ||||||
| TARGET			?= f5 | TARGET			?= f6 | ||||||
| TARGET_DIR		= targets/$(TARGET) | TARGET_DIR		= targets/$(TARGET) | ||||||
| include			$(TARGET_DIR)/target.mk | include			$(TARGET_DIR)/target.mk | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ PROJECT			= firmware | |||||||
| 
 | 
 | ||||||
| include 		$(PROJECT_ROOT)/make/base.mk | include 		$(PROJECT_ROOT)/make/base.mk | ||||||
| include			$(PROJECT_ROOT)/assets/assets.mk | include			$(PROJECT_ROOT)/assets/assets.mk | ||||||
|  | CFLAGS			+= -I$(ASSETS_COMPILED_DIR) | ||||||
| include			$(PROJECT_ROOT)/core/core.mk | include			$(PROJECT_ROOT)/core/core.mk | ||||||
| include 		$(PROJECT_ROOT)/applications/applications.mk | include 		$(PROJECT_ROOT)/applications/applications.mk | ||||||
| include			$(PROJECT_ROOT)/lib/lib.mk | include			$(PROJECT_ROOT)/lib/lib.mk | ||||||
| @ -10,7 +11,7 @@ include			$(PROJECT_ROOT)/lib/lib.mk | |||||||
| CFLAGS += -Werror -Wno-address-of-packed-member | CFLAGS += -Werror -Wno-address-of-packed-member | ||||||
| CPPFLAGS += -Werror | CPPFLAGS += -Werror | ||||||
| 
 | 
 | ||||||
| TARGET			?= f5 | TARGET			?= f6 | ||||||
| 
 | 
 | ||||||
| TARGET_DIR		= targets/$(TARGET) | TARGET_DIR		= targets/$(TARGET) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,9 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| set -x -e |  | ||||||
| 
 |  | ||||||
| rm bootloader/.obj/f*/flash || true |  | ||||||
| make -C bootloader -j9 flash |  | ||||||
| 
 |  | ||||||
| rm firmware/.obj/f*/flash || true |  | ||||||
| make -C firmware -j9 flash |  | ||||||
| @ -47,15 +47,15 @@ $(OBJ_DIR)/$(PROJECT).bin: $(OBJ_DIR)/$(PROJECT).elf | |||||||
| 	@echo "\tBIN\t" $@ | 	@echo "\tBIN\t" $@ | ||||||
| 	@$(BIN) $< $@ | 	@$(BIN) $< $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS $(ASSETS) | $(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS | ||||||
| 	@echo "\tCC\t" $< "->" $@ | 	@echo "\tCC\t" $< "->" $@ | ||||||
| 	@$(CC) $(CFLAGS) -c $< -o $@ | 	@$(CC) $(CFLAGS) -c $< -o $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS $(ASSETS) | $(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS | ||||||
| 	@echo "\tASM\t" $< "->" $@ | 	@echo "\tASM\t" $< "->" $@ | ||||||
| 	@$(AS) $(CFLAGS) -c $< -o $@ | 	@$(AS) $(CFLAGS) -c $< -o $@ | ||||||
| 
 | 
 | ||||||
| $(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS $(ASSETS) | $(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS | ||||||
| 	@echo "\tCPP\t" $< "->" $@ | 	@echo "\tCPP\t" $< "->" $@ | ||||||
| 	@$(CPP) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ | 	@$(CPP) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ | ||||||
| 
 | 
 | ||||||
| @ -67,10 +67,6 @@ $(OBJ_DIR)/upload: $(OBJ_DIR)/$(PROJECT).bin | |||||||
| 	dfu-util -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) $(DFU_OPTIONS) | 	dfu-util -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) $(DFU_OPTIONS) | ||||||
| 	touch $@ | 	touch $@ | ||||||
| 
 | 
 | ||||||
| $(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILLER) |  | ||||||
| 	@echo "\tASSETS\t" $@ |  | ||||||
| 	@$(ASSETS_COMPILLER) icons -s $(ASSETS_SOURCE_DIR) -o $(ASSETS_OUTPUT_DIR) |  | ||||||
| 
 |  | ||||||
| flash: $(OBJ_DIR)/flash | flash: $(OBJ_DIR)/flash | ||||||
| 
 | 
 | ||||||
| upload: $(OBJ_DIR)/upload | upload: $(OBJ_DIR)/upload | ||||||
| @ -104,7 +100,6 @@ bm_debug: flash | |||||||
| clean: | clean: | ||||||
| 	@echo "\tCLEAN\t" | 	@echo "\tCLEAN\t" | ||||||
| 	@$(RM) $(OBJ_DIR)/* | 	@$(RM) $(OBJ_DIR)/* | ||||||
| 	@$(RM) $(ASSETS) |  | ||||||
| 
 | 
 | ||||||
| z: clean | z: clean | ||||||
| 	$(MAKE) all | 	$(MAKE) all | ||||||
| @ -123,7 +118,7 @@ format: | |||||||
| 	@echo "Formatting sources with clang-format" | 	@echo "Formatting sources with clang-format" | ||||||
| 	@clang-format -style=file -i $(FORMAT_SOURCES) | 	@clang-format -style=file -i $(FORMAT_SOURCES) | ||||||
| 
 | 
 | ||||||
| generate_cscope_db: $(ASSETS) | generate_cscope_db: | ||||||
| 	@echo "$(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/source.list.p | 	@echo "$(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/source.list.p | ||||||
| 	@cat ~/headers.list >> $(OBJ_DIR)/source.list.p | 	@cat ~/headers.list >> $(OBJ_DIR)/source.list.p | ||||||
| 	@cat $(OBJ_DIR)/source.list.p | sed -e "s|^[^//]|$$PWD/&|g" > $(OBJ_DIR)/source.list | 	@cat $(OBJ_DIR)/source.list.p | sed -e "s|^[^//]|$$PWD/&|g" > $(OBJ_DIR)/source.list | ||||||
|  | |||||||
							
								
								
									
										51
									
								
								scripts/ReadMe.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								scripts/ReadMe.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | # About | ||||||
|  | 
 | ||||||
|  | This folder contains differnt scripts that automates routine actions. | ||||||
|  | Flashing scripts are based on cli version of [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html). | ||||||
|  | You will need to add STM32_Programmer_CLI to your path to use them. | ||||||
|  | 
 | ||||||
|  | # Flashing empty MCU/Flipper | ||||||
|  | 
 | ||||||
|  | Always flash your device in the folllowing sequence: | ||||||
|  | 
 | ||||||
|  | - OTP (Only on empty MCU) | ||||||
|  | - Core2 firmware | ||||||
|  | - Core1 firmware | ||||||
|  | - Option Bytes | ||||||
|  | 
 | ||||||
|  | ## Otp flashing | ||||||
|  | 
 | ||||||
|  | !!! Flashing incorrect OTP may permanently brick your device !!! | ||||||
|  | 
 | ||||||
|  | Normally OTP data generated and flashed at factory. | ||||||
|  | In case if MCU was replaced you'll need correct OTP data to be able to use companion applications. | ||||||
|  | Use `otp.py` to generate OTP data and `flash_otp_version_*` to flash OTP zone. | ||||||
|  | You will need exact main board revision to genrate OTP data. It can be found on main PCB. | ||||||
|  | 
 | ||||||
|  | !!! Flashing incorrect OTP may permanently brick your device !!! | ||||||
|  | 
 | ||||||
|  | ## Core2 flashing | ||||||
|  | 
 | ||||||
|  | Script blindly updates FUS and Radiostack. This operation is going to corrupt bootloader and firmware. | ||||||
|  | Reflash Core1 after Core2. | ||||||
|  | 
 | ||||||
|  | ## Core1 flashing | ||||||
|  | 
 | ||||||
|  | Script compiles and flashes both bootloader and firmware. | ||||||
|  | 
 | ||||||
|  | ## Option Bytes | ||||||
|  | 
 | ||||||
|  | !!! Setting incorrect Otion Bytes may brick your MCU !!! | ||||||
|  | 
 | ||||||
|  | Defaults are mostly OK, but there are couple things that we'd like to tune. | ||||||
|  | Also OB may be damaged, so we've made couple scripts to check and set option bytes. | ||||||
|  | 
 | ||||||
|  | !!! Setting incorrect Otion Bytes may brick your MCU !!! | ||||||
|  | 
 | ||||||
|  | Checking option bytes: | ||||||
|  | 
 | ||||||
|  | 	ob.py check | ||||||
|  | 
 | ||||||
|  | Setting option bytes: | ||||||
|  | 
 | ||||||
|  | 	ob.py set | ||||||
| @ -6,9 +6,6 @@ import subprocess | |||||||
| import io | import io | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| import re |  | ||||||
| import struct |  | ||||||
| import datetime |  | ||||||
| 
 | 
 | ||||||
| ICONS_SUPPORTED_FORMATS = ["png"] | ICONS_SUPPORTED_FORMATS = ["png"] | ||||||
| 
 | 
 | ||||||
| @ -51,7 +48,7 @@ Icon * assets_icons_get(IconName name) { | |||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Assets: | class Main: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         # command args |         # command args | ||||||
|         self.parser = argparse.ArgumentParser() |         self.parser = argparse.ArgumentParser() | ||||||
| @ -67,22 +64,6 @@ class Assets: | |||||||
|             "-o", "--output-directory", help="Output directory" |             "-o", "--output-directory", help="Output directory" | ||||||
|         ) |         ) | ||||||
|         self.parser_icons.set_defaults(func=self.icons) |         self.parser_icons.set_defaults(func=self.icons) | ||||||
|         self.parser_otp = self.subparsers.add_parser( |  | ||||||
|             "otp", help="OTP HW version generator" |  | ||||||
|         ) |  | ||||||
|         self.parser_otp.add_argument( |  | ||||||
|             "--version", type=int, help="Version", required=True |  | ||||||
|         ) |  | ||||||
|         self.parser_otp.add_argument( |  | ||||||
|             "--firmware", type=int, help="Firmware", required=True |  | ||||||
|         ) |  | ||||||
|         self.parser_otp.add_argument("--body", type=int, help="Body", required=True) |  | ||||||
|         self.parser_otp.add_argument( |  | ||||||
|             "--connect", type=int, help="Connect", required=True |  | ||||||
|         ) |  | ||||||
|         self.parser_otp.add_argument("--name", type=str, help="Name", required=True) |  | ||||||
|         self.parser_otp.add_argument("file", help="Output file") |  | ||||||
|         self.parser_otp.set_defaults(func=self.otp) |  | ||||||
|         # logging |         # logging | ||||||
|         self.logger = logging.getLogger() |         self.logger = logging.getLogger() | ||||||
| 
 | 
 | ||||||
| @ -101,39 +82,6 @@ class Assets: | |||||||
|         # execute requested function |         # execute requested function | ||||||
|         self.args.func() |         self.args.func() | ||||||
| 
 | 
 | ||||||
|     def otp(self): |  | ||||||
|         self.logger.debug(f"Generating OTP") |  | ||||||
| 
 |  | ||||||
|         if self.args.name: |  | ||||||
|             name = re.sub( |  | ||||||
|                 "[^a-zA-Z0-9.]", "", self.args.name |  | ||||||
|             )  # Filter all special characters |  | ||||||
|             name = list( |  | ||||||
|                 map(str, map(ord, name[0:8])) |  | ||||||
|             )  # Strip to 8 chars and map to ascii codes |  | ||||||
|             while len(name) < 8: |  | ||||||
|                 name.append("0") |  | ||||||
| 
 |  | ||||||
|             n1, n2, n3, n4, n5, n6, n7, n8 = map(int, name) |  | ||||||
| 
 |  | ||||||
|         data = struct.pack( |  | ||||||
|             "<BBBBLBBBBBBBB", |  | ||||||
|             self.args.version, |  | ||||||
|             self.args.firmware, |  | ||||||
|             self.args.body, |  | ||||||
|             self.args.connect, |  | ||||||
|             int(datetime.datetime.now().timestamp()), |  | ||||||
|             n1, |  | ||||||
|             n2, |  | ||||||
|             n3, |  | ||||||
|             n4, |  | ||||||
|             n5, |  | ||||||
|             n6, |  | ||||||
|             n7, |  | ||||||
|             n8, |  | ||||||
|         ) |  | ||||||
|         open(self.args.file, "wb").write(data) |  | ||||||
| 
 |  | ||||||
|     def icons(self): |     def icons(self): | ||||||
|         self.logger.debug(f"Converting icons") |         self.logger.debug(f"Converting icons") | ||||||
|         icons_c = open(os.path.join(self.args.output_directory, "assets_icons.c"), "w") |         icons_c = open(os.path.join(self.args.output_directory, "assets_icons.c"), "w") | ||||||
| @ -248,4 +196,4 @@ class Assets: | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     Assets()() |     Main()() | ||||||
							
								
								
									
										12
									
								
								scripts/flash_core1_main_swd.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								scripts/flash_core1_main_swd.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | set -x -e | ||||||
|  | 
 | ||||||
|  | SCRIPT_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" | ||||||
|  | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||||||
|  | 
 | ||||||
|  | rm $PROJECT_DIR/bootloader/.obj/f*/flash || true | ||||||
|  | make -C $PROJECT_DIR/bootloader -j9 flash | ||||||
|  | 
 | ||||||
|  | rm $PROJECT_DIR/firmware/.obj/f*/flash || true | ||||||
|  | make -C $PROJECT_DIR/firmware -j9 flash | ||||||
| @ -2,8 +2,9 @@ | |||||||
| 
 | 
 | ||||||
| set -x -e | set -x -e | ||||||
| 
 | 
 | ||||||
| COPRO_DIR="lib/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x" | SCRIPT_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" | ||||||
| 
 | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||||||
|  | COPRO_DIR="$PROJECT_DIR/lib/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x" | ||||||
| 
 | 
 | ||||||
| STM32_Programmer_CLI -c port=swd -fwupgrade $COPRO_DIR/stm32wb5x_FUS_fw_1_0_2.bin 0x080EC000 || true | STM32_Programmer_CLI -c port=swd -fwupgrade $COPRO_DIR/stm32wb5x_FUS_fw_1_0_2.bin 0x080EC000 || true | ||||||
| STM32_Programmer_CLI -c port=swd | STM32_Programmer_CLI -c port=swd | ||||||
							
								
								
									
										17
									
								
								scripts/flash_otp_version_dfu.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								scripts/flash_otp_version_dfu.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | set -x -e | ||||||
|  | 
 | ||||||
|  | if [ "$#" -ne 1 ]; then | ||||||
|  |     echo "OTP file required" | ||||||
|  |     exit | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ ! -f $1 ]; then | ||||||
|  |     echo "Unable to open OTP file" | ||||||
|  |     exit | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | STM32_Programmer_CLI -c port=usb1 -d $1 0x1FFF7000 | ||||||
|  | 
 | ||||||
|  | STM32_Programmer_CLI -c port=usb1 -r8 0x1FFF7000 8 | ||||||
							
								
								
									
										113
									
								
								scripts/ob.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										113
									
								
								scripts/ob.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,113 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | import argparse | ||||||
|  | import subprocess | ||||||
|  | import sys | ||||||
|  | import os | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Main: | ||||||
|  |     def __init__(self): | ||||||
|  |         # command args | ||||||
|  |         self.parser = argparse.ArgumentParser() | ||||||
|  |         self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") | ||||||
|  |         self.subparsers = self.parser.add_subparsers(help="sub-command help") | ||||||
|  |         self.parser_check = self.subparsers.add_parser( | ||||||
|  |             "check", help="Check Option Bytes" | ||||||
|  |         ) | ||||||
|  |         self.parser_check.set_defaults(func=self.check) | ||||||
|  |         self.parser_set = self.subparsers.add_parser("set", help="Set Option Bytes") | ||||||
|  |         self.parser_set.set_defaults(func=self.set) | ||||||
|  |         # logging | ||||||
|  |         self.logger = logging.getLogger() | ||||||
|  |         # OB | ||||||
|  |         self.ob = {} | ||||||
|  | 
 | ||||||
|  |     def __call__(self): | ||||||
|  |         self.args = self.parser.parse_args() | ||||||
|  |         if "func" not in self.args: | ||||||
|  |             self.parser.error("Choose something to do") | ||||||
|  |         # configure log output | ||||||
|  |         self.log_level = logging.DEBUG if self.args.debug else logging.INFO | ||||||
|  |         self.logger.setLevel(self.log_level) | ||||||
|  |         self.handler = logging.StreamHandler(sys.stdout) | ||||||
|  |         self.handler.setLevel(self.log_level) | ||||||
|  |         self.formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") | ||||||
|  |         self.handler.setFormatter(self.formatter) | ||||||
|  |         self.logger.addHandler(self.handler) | ||||||
|  |         # execute requested function | ||||||
|  |         self.loadOB() | ||||||
|  |         self.args.func() | ||||||
|  | 
 | ||||||
|  |     def loadOB(self): | ||||||
|  |         self.logger.info(f"Loading Option Bytes data") | ||||||
|  |         file_path = os.path.join(os.path.dirname(sys.argv[0]), "ob.data") | ||||||
|  |         file = open(file_path, "r") | ||||||
|  |         for line in file.readlines(): | ||||||
|  |             k, v, o = line.split(":") | ||||||
|  |             self.ob[k.strip()] = v.strip(), o.strip() | ||||||
|  | 
 | ||||||
|  |     def check(self): | ||||||
|  |         self.logger.info(f"Checking Option Bytes") | ||||||
|  |         try: | ||||||
|  |             output = subprocess.check_output( | ||||||
|  |                 ["STM32_Programmer_CLI", "-q", "-c port=swd", "-ob displ"] | ||||||
|  |             ) | ||||||
|  |             assert output | ||||||
|  |         except Exception as e: | ||||||
|  |             self.logger.error(f"Failed to call STM32_Programmer_CLI") | ||||||
|  |             self.logger.exception(e) | ||||||
|  |             return | ||||||
|  |         ob_correct = True | ||||||
|  |         for line in output.decode().split("\n"): | ||||||
|  |             line = line.strip() | ||||||
|  |             if not ":" in line: | ||||||
|  |                 self.logger.debug(f"Skipping line: {line}") | ||||||
|  |                 continue | ||||||
|  |             key, data = line.split(":", 1) | ||||||
|  |             key = key.strip() | ||||||
|  |             data = data.strip() | ||||||
|  |             if not key in self.ob.keys(): | ||||||
|  |                 self.logger.debug(f"Skipping key: {key}") | ||||||
|  |                 continue | ||||||
|  |             self.logger.debug(f"Processing key: {key} {data}") | ||||||
|  |             value, comment = data.split(" ", 1) | ||||||
|  |             value = value.strip() | ||||||
|  |             comment = comment.strip() | ||||||
|  |             if self.ob[key][0] != value: | ||||||
|  |                 self.logger.error( | ||||||
|  |                     f"Invalid OB: {key} {value}, expected: {self.ob[key][0]}" | ||||||
|  |                 ) | ||||||
|  |                 ob_correct = False | ||||||
|  |         if ob_correct: | ||||||
|  |             self.logger.info(f"OB Check OK") | ||||||
|  |         else: | ||||||
|  |             self.logger.error(f"OB Check FAIL") | ||||||
|  |             exit(255) | ||||||
|  | 
 | ||||||
|  |     def set(self): | ||||||
|  |         self.logger.info(f"Setting Option Bytes") | ||||||
|  |         options = [] | ||||||
|  |         for key, (value, attr) in self.ob.items(): | ||||||
|  |             if "w" in attr: | ||||||
|  |                 options.append(f"{key}={value}") | ||||||
|  |         try: | ||||||
|  |             output = subprocess.check_output( | ||||||
|  |                 [ | ||||||
|  |                     "STM32_Programmer_CLI", | ||||||
|  |                     "-q", | ||||||
|  |                     "-c port=swd", | ||||||
|  |                     f"-ob {' '.join(options)}", | ||||||
|  |                 ] | ||||||
|  |             ) | ||||||
|  |             assert output | ||||||
|  |             self.logger.info(f"Success") | ||||||
|  |         except Exception as e: | ||||||
|  |             self.logger.error(f"Failed to call STM32_Programmer_CLI") | ||||||
|  |             self.logger.exception(e) | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     Main()() | ||||||
							
								
								
									
										34
									
								
								scripts/ob_check.data
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								scripts/ob_check.data
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | RDP:0xAA:r | ||||||
|  | BOR_LEV:0x4:rw | ||||||
|  | nBOOT0:0x1:rw | ||||||
|  | nBOOT1:0x1:rw | ||||||
|  | nSWBOOT0:0x1:rw | ||||||
|  | SRAM2RST:0x0:rw | ||||||
|  | SRAM2PE:0x1:rw | ||||||
|  | nRST_STOP:0x1:rw | ||||||
|  | nRST_STDBY:0x1:rw | ||||||
|  | nRSTSHDW:0x1:rw | ||||||
|  | WWDGSW:0x1:rw | ||||||
|  | IWGDSTDBY:0x1:rw | ||||||
|  | IWDGSTOP:0x1:rw | ||||||
|  | IWDGSW:0x1:rw | ||||||
|  | IPCCDBA:0x0:rw | ||||||
|  | ESE:0x1:r | ||||||
|  | SFSA:0xCB:r | ||||||
|  | FSD:0x0:r | ||||||
|  | DDS:0x1:r | ||||||
|  | C2OPT:0x1:r | ||||||
|  | NBRSD:0x0:r | ||||||
|  | SNBRSA:0xF:r | ||||||
|  | BRSD:0x0:r | ||||||
|  | SBRSA:0xA:r | ||||||
|  | SBRV:0x32C00:r | ||||||
|  | PCROP1A_STRT:0x1FF:r | ||||||
|  | PCROP1A_END:0x0:r | ||||||
|  | PCROP_RDP:0x1:r | ||||||
|  | PCROP1B_STRT:0x1FF:r | ||||||
|  | PCROP1B_END:0x0:r | ||||||
|  | WRP1A_STRT:0xFF:r | ||||||
|  | WRP1A_END:0x0:r | ||||||
|  | WRP1B_STRT:0xFF:r | ||||||
|  | WRP1B_END:0x0:r | ||||||
							
								
								
									
										91
									
								
								scripts/otp.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										91
									
								
								scripts/otp.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | import argparse | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | import re | ||||||
|  | import struct | ||||||
|  | import datetime | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Main: | ||||||
|  |     def __init__(self): | ||||||
|  |         # command args | ||||||
|  |         self.parser = argparse.ArgumentParser() | ||||||
|  |         self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") | ||||||
|  |         self.subparsers = self.parser.add_subparsers(help="sub-command help") | ||||||
|  |         self.parser_generate = self.subparsers.add_parser( | ||||||
|  |             "generate", help="OTP HW version generator" | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "--version", type=int, help="Version", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "--firmware", type=int, help="Firmware", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "--body", type=int, help="Body", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "--connect", type=int, help="Connect", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument( | ||||||
|  |             "--name", type=str, help="Name", required=True | ||||||
|  |         ) | ||||||
|  |         self.parser_generate.add_argument("file", help="Output file") | ||||||
|  |         self.parser_generate.set_defaults(func=self.generate) | ||||||
|  |         # logging | ||||||
|  |         self.logger = logging.getLogger() | ||||||
|  | 
 | ||||||
|  |     def __call__(self): | ||||||
|  |         self.args = self.parser.parse_args() | ||||||
|  |         if "func" not in self.args: | ||||||
|  |             self.parser.error("Choose something to do") | ||||||
|  |         # configure log output | ||||||
|  |         self.log_level = logging.DEBUG if self.args.debug else logging.INFO | ||||||
|  |         self.logger.setLevel(self.log_level) | ||||||
|  |         self.handler = logging.StreamHandler(sys.stdout) | ||||||
|  |         self.handler.setLevel(self.log_level) | ||||||
|  |         self.formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") | ||||||
|  |         self.handler.setFormatter(self.formatter) | ||||||
|  |         self.logger.addHandler(self.handler) | ||||||
|  |         # execute requested function | ||||||
|  |         self.args.func() | ||||||
|  | 
 | ||||||
|  |     def generate(self): | ||||||
|  |         self.logger.debug(f"Generating OTP") | ||||||
|  | 
 | ||||||
|  |         if self.args.name: | ||||||
|  |             name = re.sub( | ||||||
|  |                 "[^a-zA-Z0-9.]", "", self.args.name | ||||||
|  |             )  # Filter all special characters | ||||||
|  |             name = list( | ||||||
|  |                 map(str, map(ord, name[0:8])) | ||||||
|  |             )  # Strip to 8 chars and map to ascii codes | ||||||
|  |             while len(name) < 8: | ||||||
|  |                 name.append("0") | ||||||
|  | 
 | ||||||
|  |             n1, n2, n3, n4, n5, n6, n7, n8 = map(int, name) | ||||||
|  | 
 | ||||||
|  |         data = struct.pack( | ||||||
|  |             "<BBBBLBBBBBBBB", | ||||||
|  |             self.args.version, | ||||||
|  |             self.args.firmware, | ||||||
|  |             self.args.body, | ||||||
|  |             self.args.connect, | ||||||
|  |             int(datetime.datetime.now().timestamp()), | ||||||
|  |             n1, | ||||||
|  |             n2, | ||||||
|  |             n3, | ||||||
|  |             n4, | ||||||
|  |             n5, | ||||||
|  |             n6, | ||||||
|  |             n7, | ||||||
|  |             n8, | ||||||
|  |         ) | ||||||
|  |         open(self.args.file, "wb").write(data) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     Main()() | ||||||
| @ -1,4 +0,0 @@ | |||||||
| #!/usr/bin/env bash |  | ||||||
| 
 |  | ||||||
| echo "RUN SYNTAX CHECK INSIDE CONTAINER" |  | ||||||
| docker-compose exec dev ./docker/syntax_check.sh |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく