flash.py
Go to the documentation of this file.
1 import os
2 import subprocess
3 
4 from typing import Optional
5 
6 import rospy
7 import rospkg
8 import rosgraph
9 import rosnode
10 import rosservice
11 
12 from rosmon_msgs.srv import StartStop, StartStopRequest
13 
14 from .utils import is_tool, write_flush, query_yes_no, prompt_options
15 from .board import BoardType, determine_board, check_firmware_version
16 
17 
18 def flash_core2(bootloader_path: str, firmware_path: str):
19  print("--> Disabling read/write protections and erasing flash")
20  subprocess.check_call("stm32loader -c rpi -f F4 -R -u -W", shell=True)
21 
22  print("--> Erasing flash")
23  subprocess.check_call("stm32loader -c rpi -f F4 -R -e", shell=True)
24 
25  print("--> Flashing bootloader")
26  subprocess.check_call(
27  f"stm32loader -c rpi -f F4 -R -w -v {bootloader_path}", shell=True
28  )
29 
30  print("--> Flashing firmware")
31  subprocess.check_call(
32  f"stm32loader -c rpi -f F4 -R -a 0x08010000 -w -v {firmware_path}", shell=True
33  )
34 
35  print("--> Flashing completed!")
36 
37 
38 def flash_leocore(firmware_path: str):
39  print("--> Disabling flash read/write protections")
40  subprocess.check_call("stm32loader -c rpi -f F4 -u -W", shell=True)
41 
42  print("--> Erasing flash")
43  subprocess.check_call("stm32loader -c rpi -f F4 -e", shell=True)
44 
45  print("--> Flashing firmware")
46  subprocess.check_call(f"stm32loader -c rpi -f F4 -w -v {firmware_path}", shell=True)
47 
48  print("--> Flashing completed!")
49 
50 
51 # pylint: disable=too-many-branches,too-many-statements
53  firmware_path: Optional[str] = None,
54  board_type: Optional[BoardType] = None,
55  check_version: bool = True,
56 ):
57  write_flush("--> Checking if stm32loader is installed.. ")
58 
59  if is_tool("stm32loader"):
60  print("YES")
61  else:
62  print("NO")
63  print(
64  "ERROR: Cannot find the stm32loader tool. "
65  "Make sure the python3-stm32loader package is installed."
66  )
67  return
68 
69 
70 
71  write_flush("--> Checking if ROS Master is online.. ")
72 
73  if rosgraph.is_master_online():
74  print("YES")
75  master_online = True
76  else:
77  print("NO")
78  master_online = False
79  if check_version:
80  print(
81  "ROS Master is not running. "
82  "Will not be able to check the current firmware version."
83  )
84  if not query_yes_no("Are you sure you want to continue?", default="no"):
85  return
86 
87 
88 
89  if master_online:
90  write_flush("--> Initializing ROS node.. ")
91  rospy.init_node("firmware_flasher", anonymous=True)
92  print("DONE")
93 
94 
95 
96  if master_online:
97  write_flush("--> Checking if rosserial node is active.. ")
98 
99  if rospy.resolve_name("serial_node") in rosnode.get_node_names():
100  print("YES")
101  serial_node_active = True
102  else:
103  print("NO")
104  serial_node_active = False
105  if check_version:
106  print(
107  "Rosserial node is not active. "
108  "Will not be able to check the current firmware version."
109  )
110  if not query_yes_no("Are you sure you want to continue?", default="no"):
111  return
112 
113 
114 
115  if master_online and serial_node_active and board_type is None:
116  write_flush("--> Trying to determine board type.. ")
117 
118  board_type = determine_board()
119 
120  if board_type is not None:
121  print("SUCCESS")
122  else:
123  print("FAIL")
124 
125 
126 
127  current_firmware_version = "<unknown>"
128 
129  if check_version and master_online and serial_node_active:
130  write_flush("--> Trying to check the current firmware version.. ")
131 
132  current_firmware_version = check_firmware_version()
133 
134  if current_firmware_version != "<unknown>":
135  print("SUCCESS")
136  else:
137  print("FAIL")
138 
139 
140 
141  if master_online and serial_node_active:
142  write_flush("--> Checking if rosmon service is available.. ")
143 
144  if rospy.resolve_name("rosmon/start_stop") in rosservice.get_service_list():
145  start_stop = rospy.ServiceProxy("rosmon/start_stop", StartStop)
146  print("YES")
147  rosmon_available = True
148  else:
149  print("NO")
150  rosmon_available = False
151 
152 
153 
154  if board_type is None:
155  print("Was not able to determine the board type. Choose the board manually: ")
156 
157  board_type = prompt_options(
158  [
159  ("LeoCore", BoardType.LEOCORE),
160  ("Husarion CORE2", BoardType.CORE2),
161  ]
162  )
163 
164 
165 
166  if firmware_path is not None:
167  firmware_version = "<unknown>"
168  else:
169  if board_type == BoardType.CORE2:
170  firmware_version = "2.1.1"
171  elif board_type == BoardType.LEOCORE:
172  firmware_version = "1.2.1"
173 
174  print(f"Current firmware version: {current_firmware_version}")
175  print(f"Version of the firmware to flash: {firmware_version}")
176 
177  if not query_yes_no("Flash the firmware?"):
178  return
179 
180 
181 
182  if master_online and serial_node_active:
183  if rosmon_available:
184  write_flush("--> Stopping the rosserial node.. ")
185  start_stop(
186  "serial_node", rospy.get_namespace().rstrip("/"), StartStopRequest.STOP
187  )
188  rospy.sleep(1)
189  print("DONE")
190  else:
191  print(
192  "WARNING: rosserial node is active, but rosmon service "
193  "is not available. You have to manually stop rosserial node "
194  "before flashing the firmware."
195  )
196  if not query_yes_no("Continue?", default="no"):
197  return
198 
199 
200 
201  if board_type == BoardType.CORE2:
202  bootloader_path = os.path.join(
203  rospkg.RosPack().get_path("leo_fw"),
204  "firmware/bootloader_1_0_0_core2.bin",
205  )
206 
207  if firmware_path is None:
208  firmware_path = os.path.join(
209  rospkg.RosPack().get_path("leo_fw"),
210  "firmware/core2_firmware.bin",
211  )
212 
213  flash_core2(bootloader_path, firmware_path)
214 
215  elif board_type == BoardType.LEOCORE:
216  if firmware_path is None:
217  firmware_path = os.path.join(
218  rospkg.RosPack().get_path("leo_fw"),
219  "firmware/leocore_firmware.bin",
220  )
221 
222  flash_leocore(firmware_path)
223 
224 
225 
226  if master_online and serial_node_active:
227  if rosmon_available:
228  write_flush("--> Starting the rosserial node.. ")
229  start_stop(
230  "serial_node", rospy.get_namespace().rstrip("/"), StartStopRequest.START
231  )
232  print("DONE")
233  else:
234  print("You can now start the rosserial node.")
leo_fw.flash.flash_firmware
def flash_firmware(Optional[str] firmware_path=None, Optional[BoardType] board_type=None, bool check_version=True)
Definition: flash.py:52
leo_fw.utils.query_yes_no
bool query_yes_no(str question, str default="yes")
Ask a yes/no question via input() and return their answer.
Definition: utils.py:34
leo_fw.flash.flash_leocore
def flash_leocore(str firmware_path)
Definition: flash.py:38
leo_fw.board.determine_board
Optional[BoardType] determine_board()
Definition: board.py:18
leo_fw.utils.is_tool
bool is_tool(str name)
Check whether an executable exists on PATH.
Definition: utils.py:19
leo_fw.utils.prompt_options
str prompt_options(list[tuple[str, Any]] options, int default=1)
Definition: utils.py:63
leo_fw.board.check_firmware_version
str check_firmware_version()
Definition: board.py:36
leo_fw.utils.write_flush
def write_flush(str msg)
Write a message to standard output and flush the buffer.
Definition: utils.py:28
leo_fw.flash.flash_core2
def flash_core2(str bootloader_path, str firmware_path)
Definition: flash.py:18


leo_fw
Author(s): Błażej Sowa , Aleksander Szymański
autogenerated on Sat Jul 6 2024 03:05:11