main.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include <stdlib.h>
  5. #include <stdarg.h>
  6. #include <limits.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <unistd.h>
  10. #include <stddef.h>
  11. #include <signal.h>
  12. #include <time.h>
  13. #include <errno.h>
  14. #include <getopt.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <gfaserial.h>
  18. #include <gfabootlmast.h>
  19. #include "main.h"
  20. #include "cmdopt.h"
  21. #include "image.h"
  22. #include "output.h"
  23. #include "modbmst.h"
  24. #include "error.h"
  25. /////////////////////////////////////////////////////////////////////////////
  26. /////////////////////////////////////////////////////////////////////////////
  27. #define _ABBR_BOOTLOADER "Boot"
  28. #define _ABBR_APPLICATION "Appl"
  29. #define _ABBR_MININET "MiNe"
  30. #define _ABBR_MODBUS "ModB"
  31. /////////////////////////////////////////////////////////////////////////////
  32. static bool g_bSig = false;
  33. /////////////////////////////////////////////////////////////////////////////
  34. static void _SigHandler(int sig)
  35. {
  36. g_bSig = !!sig;
  37. TRACE3("\n");
  38. }
  39. /////////////////////////////////////////////////////////////////////////////
  40. static int _ShowDevImgInfo(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  41. {
  42. int nRet;
  43. GFA_BL_APP_IMG_INFO aii;
  44. UNUSED(hIf);
  45. TRACE3("Getting image information.\n");
  46. TTRACE3("Getting image information");
  47. if((ctx == GfaBlmCtx_App) && ((nRet = GfaBlmGetInfoBI(hBlm, pcla->nNodeAddr, &aii)) == 0))
  48. {
  49. GfaTfuDumpImageInfo("Bootloader", &aii.bl);
  50. GfaTfuDumpImageInfo("Application", &aii.app);
  51. if( (aii.bl.nImgLength != 0xFFFFFFFF) &&
  52. (aii.bl.nImgCRC32 != 0xFFFFFFFF))
  53. {
  54. TTRACE(PLUGIN_TAG_IMG_LENGTH_BOOT, "%u", aii.bl.nImgLength);
  55. TTRACE(PLUGIN_TAG_IMG_CRC32_BOOT, "%u", aii.bl.nImgCRC32);
  56. TTRACE(PLUGIN_TAG_IMG_MATERIAL_BOOT, "%s", aii.bl.szImgMaterialNum);
  57. TTRACE(PLUGIN_TAG_IMG_BUILD_BOOT, "%s", aii.bl.szImgNameBuild);
  58. }
  59. else
  60. {
  61. TTRACE(PLUGIN_TAG_IMG_LENGTH_BOOT, "%u", 0xFFFFFFFF);
  62. TTRACE(PLUGIN_TAG_IMG_CRC32_BOOT, "%u", 0xFFFFFFFF);
  63. TTRACE(PLUGIN_TAG_IMG_MATERIAL_BOOT, "%s", "n/a");
  64. TTRACE(PLUGIN_TAG_IMG_BUILD_BOOT, "%s", "n/a");
  65. }
  66. if( (aii.app.nImgLength != 0xFFFFFFFF) &&
  67. (aii.app.nImgCRC32 != 0xFFFFFFFF))
  68. {
  69. TTRACE(PLUGIN_TAG_IMG_LENGTH_APP, "%u", aii.app.nImgLength);
  70. TTRACE(PLUGIN_TAG_IMG_CRC32_APP, "%u", aii.app.nImgCRC32);
  71. TTRACE(PLUGIN_TAG_IMG_MATERIAL_APP, "%s", aii.app.szImgMaterialNum);
  72. TTRACE(PLUGIN_TAG_IMG_BUILD_APP, "%s", aii.app.szImgNameBuild);
  73. }
  74. else
  75. {
  76. TTRACE(PLUGIN_TAG_IMG_LENGTH_APP, "%u", 0xFFFFFFFF);
  77. TTRACE(PLUGIN_TAG_IMG_CRC32_APP, "%u", 0xFFFFFFFF);
  78. TTRACE(PLUGIN_TAG_IMG_MATERIAL_APP, "%s", "n/a");
  79. TTRACE(PLUGIN_TAG_IMG_BUILD_APP, "%s", "n/a");
  80. }
  81. }
  82. else
  83. {
  84. bool bStartApp = false;
  85. if(ctx == GfaBlmCtx_App)
  86. {
  87. TRACE3("Application doesn't recognize BI command!\n");
  88. TRACE3("Starting bootloader.\n");
  89. TTRACE3("Application doesn't recognize BI command");
  90. TTRACE3("Starting bootloader");
  91. if((nRet = GfaBlmBootloaderExecute(hBlm, pcla->nNodeAddr, NULL, 1000)) != 0)
  92. {
  93. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  94. TTRACE1(GfaTfuStrError(errno));
  95. return nRet;
  96. }
  97. bStartApp = true;
  98. }
  99. if(pcla->nExBaudrate != pcla->nInitBaudrate)
  100. {
  101. TRACE3("Setting baud-rate to %u.\n", pcla->nExBaudrate);
  102. TTRACE3("Setting baud-rate to %u", pcla->nExBaudrate);
  103. if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, pcla->nNodeAddr, pcla->nExBaudrate)) != 0)
  104. {
  105. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  106. TTRACE1(GfaTfuStrError(errno));
  107. return nRet;
  108. }
  109. }
  110. if((nRet = GfaBlmGetInfoBD(hBlm, pcla->nNodeAddr, pcla->nStartAddr, &aii)) > -2)
  111. {
  112. GfaTfuDumpImageInfo("Bootloader", &aii.bl);
  113. GfaTfuDumpImageInfo("Application", &aii.app);
  114. if( (aii.bl.nImgLength != 0xFFFFFFFF) &&
  115. (aii.bl.nImgCRC32 != 0xFFFFFFFF))
  116. {
  117. TTRACE(PLUGIN_TAG_IMG_LENGTH_BOOT, "%u", aii.bl.nImgLength);
  118. TTRACE(PLUGIN_TAG_IMG_CRC32_BOOT, "%u", aii.bl.nImgCRC32);
  119. TTRACE(PLUGIN_TAG_IMG_MATERIAL_BOOT, "%s", aii.bl.szImgMaterialNum);
  120. TTRACE(PLUGIN_TAG_IMG_BUILD_BOOT, "%s", aii.bl.szImgNameBuild);
  121. }
  122. else
  123. {
  124. TTRACE(PLUGIN_TAG_IMG_LENGTH_BOOT, "%u", 0xFFFFFFFF);
  125. TTRACE(PLUGIN_TAG_IMG_CRC32_BOOT, "%u", 0xFFFFFFFF);
  126. TTRACE(PLUGIN_TAG_IMG_MATERIAL_BOOT, "%s", "n/a");
  127. TTRACE(PLUGIN_TAG_IMG_BUILD_BOOT, "%s", "n/a");
  128. }
  129. if( (aii.app.nImgLength != 0xFFFFFFFF) &&
  130. (aii.app.nImgCRC32 != 0xFFFFFFFF))
  131. {
  132. TTRACE(PLUGIN_TAG_IMG_LENGTH_APP, "%u", aii.app.nImgLength);
  133. TTRACE(PLUGIN_TAG_IMG_CRC32_APP, "%u", aii.app.nImgCRC32);
  134. TTRACE(PLUGIN_TAG_IMG_MATERIAL_APP, "%s", aii.app.szImgMaterialNum);
  135. TTRACE(PLUGIN_TAG_IMG_BUILD_APP, "%s", aii.app.szImgNameBuild);
  136. }
  137. else
  138. {
  139. TTRACE(PLUGIN_TAG_IMG_LENGTH_APP, "%u", 0xFFFFFFFF);
  140. TTRACE(PLUGIN_TAG_IMG_CRC32_APP, "%u", 0xFFFFFFFF);
  141. TTRACE(PLUGIN_TAG_IMG_MATERIAL_APP, "%s", "n/a");
  142. TTRACE(PLUGIN_TAG_IMG_BUILD_APP, "%s", "n/a");
  143. }
  144. }
  145. else
  146. {
  147. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  148. TTRACE1(GfaTfuStrError(errno));
  149. return nRet;
  150. }
  151. if(pcla->nExBaudrate != pcla->nInitBaudrate)
  152. {
  153. TRACE3("Setting baud-rate to %u.\n", pcla->nInitBaudrate);
  154. TTRACE3("Setting baud-rate to %u", pcla->nInitBaudrate);
  155. if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, pcla->nNodeAddr, pcla->nInitBaudrate)) != 0)
  156. {
  157. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  158. TTRACE1(GfaTfuStrError(errno));
  159. return nRet;
  160. }
  161. }
  162. if(bStartApp)
  163. {
  164. TRACE3("Starting application.\n");
  165. TTRACE3("Starting application");
  166. if((nRet = GfaBlmBUCmdReset(hBlm, pcla->nNodeAddr, pcla->nInitBaudrate)) != 0)
  167. {
  168. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  169. TTRACE1(GfaTfuStrError(errno));
  170. return nRet;
  171. }
  172. }
  173. }
  174. return 0;
  175. }
  176. /////////////////////////////////////////////////////////////////////////////
  177. static int _ValidateImg(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  178. {
  179. int nRet;
  180. GFA_IMG_INFO ii;
  181. char szMaterial[16], szSerial[16];
  182. UNUSED(ctx);
  183. TRACE3("Reading material number.\n");
  184. TTRACE3("Reading material number");
  185. if((nRet = GfaBlmReadMaterialAndSerialID(hBlm, pcla->nNodeAddr, szMaterial, sizeof(szMaterial), szSerial, sizeof(szSerial))) != 0)
  186. {
  187. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  188. TTRACE1(GfaTfuStrError(errno));
  189. return nRet;
  190. }
  191. if(szMaterial[0] == '\xFF')
  192. strcpy(szMaterial, "not set");
  193. if(szSerial[0] == '\xFF')
  194. strcpy(szSerial, "not set");
  195. TTRACE(PLUGIN_TAG_IMG_MATERIAL_EEPROM, szMaterial);
  196. TTRACE(PLUGIN_TAG_IMG_SERIAL_EEPROM, szSerial);
  197. GfaTfuImageFileGetInfo(hIf, &ii);
  198. TRACE2("Material number target: \"%s\"\n", szMaterial);
  199. TRACE2("Material number file: \"%s\"\n", ii.szImgMaterialNum);
  200. TTRACE2("Material number target: \"%s\"", szMaterial);
  201. TTRACE2("Material number file: \"%s\"", ii.szImgMaterialNum);
  202. if(!GfaTfuImageFileMatchMaterialNum(hIf, szMaterial))
  203. {
  204. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  205. TTRACE1(GfaTfuStrError(errno));
  206. return -1;
  207. }
  208. TRACE2("\"%s\" - Image is valid for target @ node 0x%02hhX!\n", pcla->pszImgFileBase, pcla->nNodeAddr);
  209. TTRACE2("\"%s\" - Image is valid for target @ node 0x%02hhX", pcla->pszImgFileBase, pcla->nNodeAddr);
  210. return 0;
  211. }
  212. /////////////////////////////////////////////////////////////////////////////
  213. static int _ShowMatSer(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  214. {
  215. int nRet;
  216. char szMaterial[GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH], szSerial[GFA_APP_MAX_IMG_SERIAL_NUM_LENGTH];
  217. UNUSED(hIf);
  218. UNUSED(ctx);
  219. TRACE3("Reading material and serial number.\n");
  220. TTRACE3("Reading material and serial number");
  221. if((nRet = GfaBlmReadMaterialAndSerialID(hBlm, pcla->nNodeAddr, szMaterial, sizeof(szMaterial), szSerial, sizeof(szSerial))) != 0)
  222. {
  223. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  224. TTRACE1(GfaTfuStrError(errno));
  225. return nRet;
  226. }
  227. if(szMaterial[0] == '\xFF')
  228. strcpy(szMaterial, "not set");
  229. if(szSerial[0] == '\xFF')
  230. strcpy(szSerial, "not set");
  231. TRACE2("Material and Serial number:\n");
  232. TRACE2(" Mat.Nr.: \"%s\"\n", szMaterial);
  233. TRACE2(" Serial: \"%s\"\n", szSerial);
  234. TTRACE(PLUGIN_TAG_IMG_MATERIAL_EEPROM, szMaterial);
  235. TTRACE(PLUGIN_TAG_IMG_SERIAL_EEPROM, szSerial);
  236. return nRet;
  237. }
  238. /////////////////////////////////////////////////////////////////////////////
  239. static int _SetMatSer(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  240. {
  241. int nRet;
  242. bool bStartApp = false;
  243. if(ctx == GfaBlmCtx_App)
  244. {
  245. TRACE3("Starting bootloader.\n");
  246. if((nRet = GfaBlmBootloaderExecute(hBlm, pcla->nNodeAddr, NULL, 1000)) != 0)
  247. {
  248. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  249. TTRACE1(GfaTfuStrError(errno));
  250. return nRet;
  251. }
  252. bStartApp = true;
  253. }
  254. TRACE3("Setting material and serial number.\n");
  255. TRACE2(" Mat.Nr.: \"%s\"\n", pcla->pszMaterial);
  256. TRACE2(" Serial: \"%s\"\n", pcla->pszSerial);
  257. if((nRet = GfaBlmWriteMaterialAndSerialID(hBlm, pcla->nNodeAddr, pcla->pszMaterial, pcla->pszSerial)) != 0)
  258. {
  259. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  260. TTRACE1(GfaTfuStrError(errno));
  261. return nRet;
  262. }
  263. TRACE2("Material and serial number successfully set!\n");
  264. if(bStartApp)
  265. {
  266. TRACE3("Starting application.\n");
  267. if((nRet = GfaBlmBUCmdReset(hBlm, pcla->nNodeAddr, pcla->nInitBaudrate)) != 0)
  268. {
  269. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  270. TTRACE1(GfaTfuStrError(errno));
  271. return nRet;
  272. }
  273. }
  274. return _ShowMatSer(hIf, hBlm, pcla, ctx);
  275. }
  276. /////////////////////////////////////////////////////////////////////////////
  277. static int _Ping(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  278. {
  279. int nRet;
  280. time_t t;
  281. char szTime[64];
  282. struct timespec tsStart, tsEnd, ts = {0, 0};
  283. int64_t nIntervalBoot = 0, nIntervalMini = 0, nIntervalModB = 0;
  284. HGFAMINEMST hMst = GfaBlmGetMininetMasterHandle(hBlm);
  285. HMINETDEV hDev = GfaMininetMasterGetDeviceHandle(hMst);
  286. HGFAMBMST hMbm = NULL;
  287. GFA_SER_CFG_PARAMS scp, scpSave;
  288. UNUSED(hIf);
  289. if(ctx == GfaBlmCtx_ModB)
  290. {
  291. if(!(hMbm = GfaMbMstOpen(hMst, pcla->nModbBaudrate, pcla->modbParity, pcla->nModbusCtrlReg)))
  292. return -1;
  293. GfaMbMstSetVerbosity(hMbm, pcla->nVerbosity);
  294. if(GfaMininetDeviceGetConfigParams(hDev, &scp, sizeof(scp)) != sizeof(scp))
  295. {
  296. GfaMbMstClose(hMbm);
  297. return -1;
  298. }
  299. memcpy(&scpSave, &scp, sizeof(scpSave));
  300. scp.parity = pcla->modbParity;
  301. scp.baud = pcla->nModbBaudrate;
  302. if(GfaMininetDeviceSetConfigParams(hDev, &scp, sizeof(scp)) != 0)
  303. {
  304. GfaMbMstClose(hMbm);
  305. return -1;
  306. }
  307. }
  308. do
  309. {
  310. t = time(NULL);
  311. strftime(szTime, sizeof(szTime), "%T", localtime(&t));
  312. GfaTfuGetClock(&tsStart);
  313. if(ctx == GfaBlmCtx_ModB)
  314. {
  315. if((nRet = GfaMbMstPing(hMbm, pcla->nModbusSlvID)) == 0)
  316. {
  317. GfaTfuGetClock(&tsEnd);
  318. nIntervalModB = GfaTfuClockDiff(&tsEnd, &tsStart);
  319. TRACE2("Slave 0x%02hhX [%s] ping success [%.1f ms] - %s.\n", pcla->nModbusSlvID, _ABBR_MODBUS, (double)nIntervalModB / 1000000.0, szTime);
  320. TTRACE2("Slave 0x%02hhX [%s] ping success [%.1f ms] - %s", pcla->nModbusSlvID, _ABBR_MODBUS, (double)nIntervalModB / 1000000.0, szTime);
  321. }
  322. else
  323. {
  324. TRACE1("Slave 0x%02hhX [%s] ping error: %s - %s.\n", pcla->nModbusSlvID, _ABBR_MODBUS, GfaTfuStrError(errno), szTime);
  325. TTRACE1("Slave 0x%02hhX [%s] ping error: %s - %s", pcla->nModbusSlvID, _ABBR_MODBUS, GfaTfuStrError(errno), szTime);
  326. }
  327. }
  328. else if((nRet = GfaBlmMininetPing(hBlm, pcla->nNodeAddr)) == 0)
  329. {
  330. GfaTfuGetClock(&tsEnd);
  331. nIntervalMini = GfaTfuClockDiff(&tsEnd, &tsStart);
  332. GfaTfuGetClock(&tsStart);
  333. if((nRet = GfaBlmBUCmdPing(hBlm, pcla->nNodeAddr)) != 0)
  334. {
  335. if( (ctx == GfaBlmCtx_Boot) ||
  336. (errno != -MINET_SLAVE_STATUS_INDEX_INVALID_PARAM))
  337. {
  338. if(errno == -MINET_SLAVE_STATUS_INDEX_ERROR)
  339. {
  340. if((nRet = GfaBlmResetSlaveIndex(hBlm, pcla->nNodeAddr)) != 0)
  341. {
  342. TRACE1("Node 0x%02hhX [%s] ping error: %s - %s.\n", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, GfaTfuStrError(errno), szTime);
  343. TTRACE1("Node 0x%02hhX [%s] ping error: %s - %s", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, GfaTfuStrError(errno), szTime);
  344. break;
  345. }
  346. if((ctx = GfaBlmGetExecutionContext(hBlm, pcla->nNodeAddr)) == GfaBlmCtx_Err)
  347. {
  348. TRACE1("Node 0x%02hhX ping error: %s - %s.\n", pcla->nNodeAddr, GfaTfuStrError(errno), szTime);
  349. TTRACE1("Node 0x%02hhX ping error: %s - %s", pcla->nNodeAddr, GfaTfuStrError(errno), szTime);
  350. break;
  351. }
  352. continue;
  353. }
  354. }
  355. else
  356. {
  357. nRet = 0;
  358. }
  359. }
  360. if(nRet == 0)
  361. {
  362. GfaTfuGetClock(&tsEnd);
  363. nIntervalBoot = GfaTfuClockDiff(&tsEnd, &tsStart);
  364. TRACE2("Node 0x%02hhX [%s] ping success [%.1f ms] - %s.\n", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, (double)nIntervalBoot / 1000000.0, szTime);
  365. TTRACE2("Node 0x%02hhX [%s] ping success [%.1f ms] - %s", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, (double)nIntervalBoot / 1000000.0, szTime);
  366. }
  367. else
  368. {
  369. TRACE2("Node 0x%02hhX [%s] ping success [%.1f ms] - %s.\n", pcla->nNodeAddr, _ABBR_MININET, (double)nIntervalMini / 1000000.0, szTime);
  370. TTRACE2("Node 0x%02hhX [%s] ping success [%.1f ms] - %s", pcla->nNodeAddr, _ABBR_MININET, (double)nIntervalMini / 1000000.0, szTime);
  371. TRACE1("Node 0x%02hhX [%s] ping error: %s - %s.\n", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, GfaTfuStrError(errno), szTime);
  372. TTRACE1("Node 0x%02hhX [%s] ping error: %s - %s", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, GfaTfuStrError(errno), szTime);
  373. }
  374. }
  375. else
  376. {
  377. if(errno == -MINET_SLAVE_STATUS_INDEX_ERROR)
  378. {
  379. if((nRet = GfaBlmResetSlaveIndex(hBlm, pcla->nNodeAddr)) != 0)
  380. {
  381. TRACE1("Node 0x%02hhX [%s] ping error: %s - %s.\n", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, GfaTfuStrError(errno), szTime);
  382. TTRACE1("Node 0x%02hhX [%s] ping error: %s - %s", pcla->nNodeAddr, (ctx == GfaBlmCtx_Boot) ? _ABBR_BOOTLOADER : _ABBR_APPLICATION, GfaTfuStrError(errno), szTime);
  383. break;
  384. }
  385. continue;
  386. }
  387. TRACE1("Node 0x%02hhX [%s] ping error: %s - %s.\n", pcla->nNodeAddr, _ABBR_MININET, GfaTfuStrError(errno), szTime);
  388. TTRACE1("Node 0x%02hhX [%s] ping error: %s - %s", pcla->nNodeAddr, _ABBR_MININET, GfaTfuStrError(errno), szTime);
  389. }
  390. if(pcla->nPingIntervalSec > 0)
  391. {
  392. ts.tv_sec = pcla->nPingIntervalSec;
  393. if(nanosleep(&ts, NULL) < 0)
  394. break;
  395. }
  396. }
  397. while(pcla->nPingIntervalSec && !g_bSig);
  398. if(hMbm)
  399. {
  400. GfaMbMstClose(hMbm);
  401. if(GfaMininetDeviceSetConfigParams(hDev, &scpSave, sizeof(scpSave)) != 0)
  402. return -1;
  403. }
  404. return nRet;
  405. }
  406. /////////////////////////////////////////////////////////////////////////////
  407. static int _UploadImg(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  408. {
  409. int nRet;
  410. uint32_t nCntFlashPages;
  411. size_t nImgLength;
  412. const void *pImgData;
  413. if((nRet = _ValidateImg(hIf, hBlm, pcla, ctx)) == 0)
  414. {
  415. if(ctx == GfaBlmCtx_App)
  416. {
  417. TRACE3("Starting bootloader.\n");
  418. if((nRet = GfaBlmBootloaderExecute(hBlm, pcla->nNodeAddr, NULL, 1000)) != 0)
  419. {
  420. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  421. TTRACE1(GfaTfuStrError(errno));
  422. return nRet;
  423. }
  424. }
  425. if(pcla->nExBaudrate != pcla->nBootBaudrate)
  426. {
  427. TRACE3("Setting baud-rate to %u.\n", pcla->nExBaudrate);
  428. if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, pcla->nNodeAddr, pcla->nExBaudrate)) != 0)
  429. {
  430. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  431. TTRACE1(GfaTfuStrError(errno));
  432. return nRet;
  433. }
  434. }
  435. pImgData = GfaTfuImageFileGetData(hIf);
  436. nImgLength = GfaTfuImageFileGetSize(hIf);
  437. nCntFlashPages = (nImgLength + GFA_BOOTLOADER_FLASH_PAGE_SIZE - 1) / GFA_BOOTLOADER_FLASH_PAGE_SIZE;
  438. if((nRet = GfaBlmBUCmdDownload(hBlm, pcla->nNodeAddr, pcla->nStartAddr, nImgLength, nCntFlashPages * pcla->nPageErsaeTime)) == 0)
  439. {
  440. if((nRet = GfaBlmBUCmdSendData(hBlm, pcla->nNodeAddr, pImgData, nImgLength, pcla->nBlockSize)) != 0)
  441. {
  442. if(pcla->nExBaudrate != pcla->nBootBaudrate)
  443. {
  444. TRACE3("Trying to reset baud-rate to %u.\n", pcla->nBootBaudrate);
  445. if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, pcla->nNodeAddr, pcla->nBootBaudrate)) != 0)
  446. {
  447. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  448. TTRACE1(GfaTfuStrError(errno));
  449. }
  450. }
  451. return -1;
  452. }
  453. }
  454. else
  455. {
  456. if(pcla->nExBaudrate != pcla->nBootBaudrate)
  457. {
  458. TRACE3("Trying to reset baud-rate to %u.\n", pcla->nBootBaudrate);
  459. if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, pcla->nNodeAddr, pcla->nBootBaudrate)) != 0)
  460. {
  461. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  462. TTRACE1(GfaTfuStrError(errno));
  463. }
  464. }
  465. return -1;
  466. }
  467. TRACE3("Starting application.\n");
  468. if((nRet = GfaBlmBUCmdReset(hBlm, pcla->nNodeAddr, pcla->nInitBaudrate)) != 0)
  469. {
  470. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  471. TTRACE1(GfaTfuStrError(errno));
  472. return nRet;
  473. }
  474. }
  475. return nRet;
  476. }
  477. /////////////////////////////////////////////////////////////////////////////
  478. static int _ResetBootloader(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  479. {
  480. int nRet;
  481. UNUSED(hIf);
  482. if(ctx == GfaBlmCtx_App)
  483. {
  484. TRACE2("Application already executing!\n");
  485. TTRACE2("Application already executing");
  486. return 0; // no error
  487. }
  488. TRACE3("Resetting bootloader.\n");
  489. TTRACE3("Resetting bootloader");
  490. if((nRet = GfaBlmBUCmdReset(hBlm, pcla->nNodeAddr, pcla->nInitBaudrate)) != 0)
  491. {
  492. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  493. TTRACE1(GfaTfuStrError(errno));
  494. return nRet;
  495. }
  496. return 0;
  497. }
  498. /////////////////////////////////////////////////////////////////////////////
  499. static int _ReviveBootloader(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx, bool bImplicitCall)
  500. {
  501. int nLen, nRet = 0, nCnt = 0;
  502. uint8_t nStatus;
  503. struct timespec ts = {0, 250000000};
  504. UNUSED(hIf);
  505. if(ctx == GfaBlmCtx_App)
  506. {
  507. TRACE1("Bootloader not executing!\n");
  508. TTRACE1("Bootloader not executing");
  509. return 0;
  510. }
  511. uint8_t data[128], frm[256], rx[256], cmd[256];
  512. size_t nCbData = sizeof(data);
  513. HGFAMINEMST hMst = GfaBlmGetMininetMasterHandle(hBlm);
  514. memset(data, 0, sizeof(data));
  515. if(!bImplicitCall)
  516. TRACE2("Reviving bootloader.\n");
  517. while(!g_bSig)
  518. {
  519. nLen = GfaBlmBuildCmdDataPacket("BU", 0, data, nCbData, cmd, sizeof(cmd), false);
  520. nLen = GfaMininetMasterBuildFrame(hMst, pcla->nNodeAddr, 0, cmd, nLen, frm, sizeof(frm));
  521. if((nRet = GfaMininetMasterTransmitFrame(hMst, frm, nLen)) != nLen)
  522. {
  523. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  524. TTRACE1(GfaTfuStrError(errno));
  525. return -1;
  526. }
  527. if((nRet = GfaMininetMasterReceiveFrame(hMst, rx, sizeof(rx), true)) <= 0)
  528. {
  529. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  530. TTRACE1(GfaTfuStrError(errno));
  531. return -1;
  532. }
  533. nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, pcla->nNodeAddr, rx, nRet, true, &nStatus);
  534. if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE)
  535. {
  536. TRACE1("Error: %s!\n", GfaTfuStrError(-nStatus));
  537. TTRACE1(GfaTfuStrError(-nStatus));
  538. return -1;
  539. }
  540. else if(nRet == MINET_SLAVE_RESPONSE_SUCCESS)
  541. {
  542. nCbData = 0;
  543. }
  544. else if(nRet == MINET_SLAVE_RESPONSE_ACK)
  545. {
  546. nCbData = sizeof(data);
  547. ++nCnt;
  548. }
  549. if(nCnt >= 3)
  550. return 0;
  551. if(nanosleep(&ts, NULL) < 0)
  552. break;
  553. }
  554. return nRet;
  555. }
  556. /////////////////////////////////////////////////////////////////////////////
  557. static int _ModbusStartBootloader(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  558. {
  559. HGFAMINEMST hMst = GfaBlmGetMininetMasterHandle(hBlm);
  560. UNUSED(hIf);
  561. UNUSED(ctx);
  562. TRACE3("Starting bootloader.\n");
  563. if(hMst)
  564. {
  565. HGFAMBMST hMbm = GfaMbMstOpen(hMst, pcla->nModbBaudrate, pcla->modbParity, pcla->nModbusCtrlReg);
  566. if(hMbm)
  567. {
  568. int nRet;
  569. GfaMbMstSetVerbosity(hMbm, pcla->nVerbosity);
  570. if((nRet = GfaMbMstBootloaderExecute(hMbm, pcla->nModbusSlvID)) == 0)
  571. {
  572. if(pcla->nNodeAddr)
  573. GfaMininetMasterResetLocalIndex(hMst, pcla->nNodeAddr);
  574. }
  575. else
  576. {
  577. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  578. TTRACE1(GfaTfuStrError(errno));
  579. }
  580. GfaMbMstClose(hMbm);
  581. return nRet;
  582. }
  583. }
  584. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  585. TTRACE1(GfaTfuStrError(errno));
  586. return -1;
  587. }
  588. /////////////////////////////////////////////////////////////////////////////
  589. static int _StartBootloader(HIMGFILE hIf, HGFABLM hBlm, LPCCMD_LINE_ARGS pcla, GFA_BLM_EXEC_CONTEXT ctx)
  590. {
  591. int nRet;
  592. if(ctx == GfaBlmCtx_Boot)
  593. {
  594. TRACE2("Bootloader already executing!\n");
  595. TTRACE2("Bootloader already executing");
  596. return 0; // no error
  597. }
  598. else if(ctx == GfaBlmCtx_ModB)
  599. {
  600. return _ModbusStartBootloader(hIf, hBlm, pcla, ctx);
  601. }
  602. TRACE3("Starting bootloader.\n");
  603. TTRACE3("Starting bootloader");
  604. if((nRet = GfaBlmBootloaderExecute(hBlm, pcla->nNodeAddr, NULL, 1000)) != 0)
  605. {
  606. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  607. TTRACE1(GfaTfuStrError(errno));
  608. return nRet;
  609. }
  610. return 0;
  611. }
  612. /////////////////////////////////////////////////////////////////////////////
  613. static bool _AutoBaud(HGFABLM hBlm, LPCMD_LINE_ARGS pcla)
  614. {
  615. const uint32_t nBaudrates[] = {19200, 9600, 38400, 57600, 115200, 230400, 4800, 460800/*, 921600, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400*/};
  616. const uint8_t nParities[] = {'N', 'E', 'O'};
  617. size_t nCntParities = pcla->bForceAllParities ? _countof(nParities) : 1;
  618. HGFAMINEMST hMst = GfaBlmGetMininetMasterHandle(hBlm);
  619. HMINETDEV hDev = GfaMininetMasterGetDeviceHandle(hMst);
  620. if(hDev)
  621. {
  622. int nRet;
  623. size_t i, j;
  624. bool bBaudrateHit = false;
  625. struct timeval tvRX = {0, 100000};
  626. GFA_SER_CFG_PARAMS scp, scpSave;
  627. if(GfaMininetDeviceGetConfigParams(hDev, &scp, sizeof(scp)) != sizeof(scp))
  628. return false;
  629. memcpy(&scpSave, &scp, sizeof(scpSave));
  630. GfaMininetMasterSaveTimeouts(hMst);
  631. GfaMininetMasterSetTimeouts(hMst, &tvRX, NULL);
  632. for(i = 0; i < nCntParities; ++i)
  633. {
  634. scp.parity = nParities[i];
  635. for(j = 0; j < _countof(nBaudrates); ++j)
  636. {
  637. scp.baud = nBaudrates[j];
  638. TRACE4("MiniNet - Try to connect @ %u,8,1,%c\n", scp.baud, scp.parity);
  639. if(GfaMininetDeviceSetConfigParams(hDev, &scp, sizeof(scp)) != 0)
  640. {
  641. nRet = -1;
  642. break;
  643. }
  644. if((nRet = GfaBlmResetSlaveIndex(hBlm, pcla->nNodeAddr)) == 0)
  645. {
  646. pcla->nInitBaudrate = nBaudrates[j];
  647. if(!pcla->nExBaudrate)
  648. pcla->nExBaudrate = pcla->nInitBaudrate;
  649. bBaudrateHit = true;
  650. TRACE3("Detected MiniNet connection @ %u,8,1,%c\n", scp.baud, scp.parity);
  651. TTRACE3("Detected MiniNet connection @ %u,8,1,%c", scp.baud, scp.parity);
  652. break;
  653. }
  654. usleep(10000);
  655. }
  656. if(bBaudrateHit)
  657. break;
  658. }
  659. GfaMininetMasterRestoreTimeouts(hMst);
  660. if(nRet)
  661. {
  662. GfaMininetDeviceSetConfigParams(hDev, &scpSave, sizeof(scpSave));
  663. return false;
  664. }
  665. return true;
  666. }
  667. return false;
  668. }
  669. /////////////////////////////////////////////////////////////////////////////
  670. static bool _ModbusAutobaud(HGFABLM hBlm, LPCMD_LINE_ARGS pcla)
  671. {
  672. const uint32_t nBaudrates[] = {19200, 9600, 38400, 57600, 115200, 230400, 4800, 460800/*, 921600, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400*/};
  673. const uint8_t nParities[] = {'E', 'O', 'N'};
  674. size_t nCntParities = pcla->bForceAllParities ? _countof(nParities) : 2;
  675. uint32_t i, j;
  676. HGFAMINEMST hMst = GfaBlmGetMininetMasterHandle(hBlm);
  677. HMINETDEV hDev = GfaMininetMasterGetDeviceHandle(hMst);
  678. if(hDev)
  679. {
  680. HGFAMBMST hMbm;
  681. GFA_SER_CFG_PARAMS scp, scpSave;
  682. if(GfaMininetDeviceGetConfigParams(hDev, &scp, sizeof(scp)) != sizeof(scp))
  683. return false;
  684. memcpy(&scpSave, &scp, sizeof(scpSave));
  685. hMbm = GfaMbMstOpen(hMst, pcla->nModbBaudrate, pcla->modbParity, pcla->nModbusCtrlReg);
  686. if(hMbm)
  687. {
  688. int nRet;
  689. bool bBaudrateHit = false;
  690. struct timeval tvRX = {0, 200000};
  691. GfaMbMstSetVerbosity(hMbm, pcla->nVerbosity);
  692. GfaMininetMasterSaveTimeouts(hMst);
  693. GfaMininetMasterSetTimeouts(hMst, &tvRX, NULL);
  694. for(i = 0; i < nCntParities; ++i)
  695. {
  696. scp.parity = nParities[i];
  697. for(j = 0; j < _countof(nBaudrates); ++j)
  698. {
  699. scp.baud = nBaudrates[j];
  700. TRACE4("Modbus - Try to connect @ %u,8,1,%c\n", scp.baud, scp.parity);
  701. if(GfaMininetDeviceSetConfigParams(hDev, &scp, sizeof(scp)) != 0)
  702. {
  703. nRet = -1;
  704. break;
  705. }
  706. if((nRet = GfaMbMstPing(hMbm, pcla->nModbusSlvID)) == 0)
  707. {
  708. pcla->modbParity = nParities[i];
  709. pcla->nModbBaudrate = nBaudrates[j];
  710. TRACE3("Detected Modbus application @ %u,8,1,%c\n", pcla->nModbBaudrate, pcla->modbParity);
  711. TTRACE3("Detected Modbus application @ %u,8,1,%c", pcla->nModbBaudrate, pcla->modbParity);
  712. bBaudrateHit = true;
  713. GfaMbMstWaitFrameDelay(hMbm);
  714. break;
  715. }
  716. GfaMbMstWaitFrameDelay(hMbm);
  717. }
  718. if(bBaudrateHit)
  719. break;
  720. }
  721. GfaMininetMasterRestoreTimeouts(hMst);
  722. GfaMbMstClose(hMbm);
  723. if(GfaMininetDeviceSetConfigParams(hDev, &scpSave, sizeof(scpSave)) != 0)
  724. return false;
  725. return (nRet == 0);
  726. }
  727. }
  728. return false;
  729. }
  730. /////////////////////////////////////////////////////////////////////////////
  731. static void _OnUploadProgress(const char *pszFile, int nLine, LPGFA_BLM_DL_PROGRESS_PARAMS pdlpp)
  732. {
  733. if(pdlpp)
  734. {
  735. static struct timespec tsStart, tsEnd;
  736. static uint32_t nBlockNr;
  737. static int nOldPerc;
  738. LPCCMD_LINE_ARGS pcla = (LPCCMD_LINE_ARGS)pdlpp->pParam;
  739. int64_t nInterval = 0;
  740. char szPercString[8];
  741. int nPerc;
  742. switch(pdlpp->nCtx)
  743. {
  744. case GBDPS_Error:
  745. //#ifdef _DEBUG
  746. #if 0
  747. TRACE1("Error: %s:%d: %s!\n", pszFile, nLine, GfaBlmStrError(pdlpp->nErrorCode));
  748. #else // _DEBUG
  749. UNUSED(pszFile);
  750. UNUSED(nLine);
  751. TRACE1("Error: %s!\n", GfaBlmStrError(pdlpp->nErrorCode));
  752. TTRACE1(GfaBlmStrError(pdlpp->nErrorCode));
  753. #endif // _DEBUG
  754. break;
  755. case GBDPS_StartEraseFlash:
  756. TRACE2("Start download of %u bytes to node 0x%02hhX @ address 0x%X.\n", pdlpp->nCbTotal, pdlpp->nNodeAddr, pdlpp->nFlashStartAddr);
  757. TRACE2("Erasing %u flash pages.\n", pdlpp->nCntFlashPages);
  758. GfaTfuGetClock(&tsStart);
  759. break;
  760. case GBDPS_EndEraseFlash:
  761. GfaTfuGetClock(&tsEnd);
  762. nInterval = GfaTfuClockDiff(&tsEnd, &tsStart);
  763. TRACE2("Erased %u flash pages in %lld ms (%.1f ms/page).\n", pdlpp->nCntFlashPages, nInterval / 1000000, ((double)nInterval / 1000000.0) / (double)pdlpp->nCntFlashPages);
  764. break;
  765. case GBDPS_StartUploadBlocks:
  766. nBlockNr = 0;
  767. nOldPerc = -1;
  768. TRACE2("Start sending data to node 0x%02hhX - block size: %u bytes.\n", pdlpp->nNodeAddr, pdlpp->nCbBlock);
  769. GfaTfuGetClock(&tsStart);
  770. break;
  771. case GBDPS_UploadBlock:
  772. if(!pcla || !pcla->bNoProgressBlock)
  773. {
  774. if((nPerc = GfaTfuGetPercentString(pdlpp->nCbSent, pdlpp->nCbTotal, szPercString, sizeof(szPercString)))!= nOldPerc)
  775. {
  776. if((pcla->nVerbosity < 4) && (nBlockNr > 0))
  777. TRACE2("\b\b\b\b\b");
  778. TRACE2("%s", szPercString);
  779. nOldPerc = nPerc;
  780. }
  781. }
  782. ++nBlockNr;
  783. break;
  784. case GBDPS_EndUploadBlocks:
  785. GfaTfuGetClock(&tsEnd);
  786. nInterval = GfaTfuClockDiff(&tsEnd, &tsStart);
  787. if(!pcla || !pcla->bNoProgressBlock)
  788. TRACE2(" - Done.\n");
  789. TRACE2("Sent %u blocks to node 0x%02hhX in %llu ms (%.1f Kb/s).\n", nBlockNr, pdlpp->nNodeAddr, nInterval / 1000000, (double)pdlpp->nCbTotal / ((double)nInterval / 1000000000.0) / 1024.0);
  790. break;
  791. }
  792. }
  793. }
  794. /////////////////////////////////////////////////////////////////////////////
  795. /////////////////////////////////////////////////////////////////////////////
  796. /////////////////////////////////////////////////////////////////////////////
  797. int main(int argc, char* argv[])
  798. {
  799. int nRet = 0;
  800. HIMGFILE hIf = NULL; // Handle to the image file
  801. HGFABLM hBlm = NULL; // Handle to the bootloader master
  802. CMD_LINE_ARGS cla; // structure that receives all required options and parameters
  803. struct sigaction sa;
  804. /////////////////////////////////////////////////////////////////////////
  805. // process command line
  806. GfaTfuCmdOptInitOpts(&cla); // set options defaults
  807. GfaTfuCmdOptParse(argc, argv, &cla); // parse the command line
  808. if((nRet = GfaTfuCmdOptProcess(&cla)) != 0) // validate the options in their context
  809. {
  810. if(nRet > 0)
  811. {
  812. if(!cla.bPluginMode)
  813. {
  814. GfaTfuCmdOptDisplayHelp(cla.nQuestionMarks == 3); // show Help and exit
  815. return 0;
  816. }
  817. else
  818. {
  819. TTRACE1("Invalid command or option");
  820. TTRACEEXIT("1");
  821. return 1;
  822. }
  823. }
  824. else if(nRet == (int)GFA_FU_ERROR_MISSING_COMMAND_OPT) // A required option is missing
  825. {
  826. TRACE0("Error: %s: %s!\n", GfaTfuStrError(nRet), GfaTfuCmdOpt2String(cla.nMissingOptFlags));
  827. TTRACE1("%s: %s", GfaTfuStrError(nRet), GfaTfuCmdOpt2String(cla.nMissingOptFlags));
  828. }
  829. else if(nRet == (int)GFA_FU_ERROR_MULTIPLE_COMMANDS) // Multiple commands were given
  830. {
  831. TRACE0("Error: %s: %s!\n", GfaTfuStrError(nRet), GfaTfuCmdOpt2String(cla.nCmdFlags));
  832. TTRACE1("%s: %s", GfaTfuStrError(nRet), GfaTfuCmdOpt2String(cla.nCmdFlags));
  833. }
  834. else // Another error occured
  835. {
  836. TRACE0("Error: %s!\n", GfaTfuStrError(nRet));
  837. TTRACE1("%s", GfaTfuStrError(nRet));
  838. }
  839. TTRACEEXIT("%d", nRet);
  840. return nRet;
  841. }
  842. // At this point all command line options have been parsed and validated and the cla structure
  843. // contains all necessary parameters for the requested command.
  844. // Dump an overview of the provided command and the explicitly set options.
  845. GfaTfuCmdOptDumpOptions(&cla);
  846. /////////////////////////////////////////////////////////////////////////
  847. // configure signal handling
  848. memset(&sa, 0, sizeof(sa));
  849. sa.sa_handler = _SigHandler;
  850. sigaction(SIGHUP, &sa, NULL); // handle user's terminal disconnect
  851. sigaction(SIGQUIT, &sa, NULL); // handle Ctrl + '\'
  852. sigaction(SIGTERM, &sa, NULL); // handle normal termination
  853. sigaction(SIGABRT, &sa, NULL); // handle abnormal termination (i.e. abort())
  854. sigaction(SIGINT, &sa, NULL); // handle Ctrl + 'C'
  855. sa.sa_handler = SIG_IGN;
  856. sigaction(SIGTSTP, &sa, NULL); // ignore Ctrl + 'Z'
  857. sigaction(SIGSTOP, &sa, NULL); // ignore Stop
  858. sigaction(SIGCONT, &sa, NULL); // ignore Continue
  859. sigaction(SIGCHLD, &sa, NULL); // ignore child process termination
  860. sigaction(0, &sa, NULL); // ignore shell termination
  861. /////////////////////////////////////////////////////////////////////////
  862. do
  863. {
  864. GFA_BLM_CFG_PARAMS blmcp; // bootloader master configuration struct
  865. memset(&blmcp, 0, sizeof(blmcp));
  866. if(cla.bNeedImgFile) // If the given command requires an image file, open it.
  867. { // This also performs some basic validations on the file.
  868. GFA_IMG_INFO ii;
  869. TRACE3("Opening image file %s.\n", cla.pszImgFile);
  870. TTRACE3("Opening image file %s", cla.pszImgFile);
  871. if(!(hIf = GfaTfuImageFileOpen(cla.pszImgFile, cla.nStartAddr, true)))
  872. {
  873. TRACE1("Error: %s!\n", GfaTfuStrError(errno)); // Something is wrong with the file
  874. TTRACE1(GfaTfuStrError(errno));
  875. break;
  876. }
  877. GfaTfuImageFileGetInfo(hIf, &ii);
  878. TTRACE(PLUGIN_TAG_IMG_LENGTH_FILE, "%u", ii.nImgLength);
  879. TTRACE(PLUGIN_TAG_IMG_CRC32_FILE, "%u", ii.nImgCRC32);
  880. TTRACE(PLUGIN_TAG_IMG_MATERIAL_FILE, "%s", ii.szImgMaterialNum);
  881. TTRACE(PLUGIN_TAG_IMG_BUILD_FILE, "%s", ii.szImgNameBuild);
  882. if(cla.bShowFileImgInfo) // If only the file's image information was requested, dump it and exit.
  883. {
  884. GfaTfuDumpImageInfo(cla.pszImgFile, &ii);
  885. break;
  886. }
  887. }
  888. // As of this point we require a connection to the target.
  889. // In our case we request the serial device interface,
  890. // which is in turn used by the abstract mininet device
  891. if(GfaSerialGetDeviceInterface(&blmcp.mmcp.devcfg.itf))
  892. {
  893. GFA_SER_CFG_PARAMS scp; // serial device configuration parameters
  894. memset(&scp, 0, sizeof(scp));
  895. /////////////////////////////////////////////////////////////////
  896. // serial device configuration
  897. scp.baud = cla.nInitBaudrate; // open with default bootloader baud-rate
  898. scp.data = 8; // always use 8 data bits
  899. scp.stop = 1; // always use 1 stop bit
  900. scp.parity = 'N'; // open with mininet default
  901. #ifdef _TARGET_BUILD
  902. scp.bHandleTxEcho = true; // On GfA Sitara targets we have to handle transmit echo!
  903. scp.bIsRS485 = true; // Interface is a RS485
  904. #endif // _TARGET_BUILD
  905. /////////////////////////////////////////////////////////////////
  906. // mininet master device configuration
  907. // since the mininet master handles the opening and closing of the
  908. // mininet device, which is the abstraction layer of our physical
  909. // device and in turn handles our serial device, we provide the
  910. // appropriate parameters.
  911. blmcp.mmcp.devcfg.pszDeviceName = cla.pszDevName; // name of the interface, i.e. "/dev/ttyO4"
  912. blmcp.mmcp.devcfg.pDevParams = &scp; // pointer to the serial device configuration parameters
  913. blmcp.mmcp.devcfg.nSizeDevParams = sizeof(scp); // size of the serial device configuration parameters
  914. /////////////////////////////////////////////////////////////////
  915. // bootloader master configuration
  916. blmcp.pfnDlProgress = _OnUploadProgress; // progress output function for the image upload
  917. blmcp.pUserParam = &cla; // will be passed to the progress function
  918. /////////////////////////////////////////////////////////////////
  919. // open a bootloader master instance
  920. TRACE3("Opening bootloader master.\n");
  921. TTRACE3("Opening bootloader master");
  922. if((hBlm = GfaBlmOpen(&blmcp)))
  923. {
  924. // At this point the bootloader master, the mininet master and the mininet device
  925. // have been opened and initialized successfully
  926. GFA_BLM_EXEC_CONTEXT ctx;
  927. bool bModbusAppDetected = false;
  928. GfaBlmSetVerbosity(hBlm, cla.nVerbosity); // Set the verbosity of the bootloader master and it's descendants
  929. TRACE3("Connecting to target.\n");
  930. TTRACE3("Connecting to target");
  931. if(!_AutoBaud(hBlm, &cla)) // Try to detect the mininet baudrate and parity
  932. {
  933. // If no mininet connection could be detected, try to scan for a modbus connection, given that
  934. // a valid modbus slave-id has been provided.
  935. if( !MODBUS_IS_VALID_SLAVE_ID(cla.nModbusSlvID) ||
  936. !(bModbusAppDetected = _ModbusAutobaud(hBlm, &cla)))
  937. {
  938. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  939. TTRACE1(GfaTfuStrError(errno));
  940. break;
  941. }
  942. }
  943. if(bModbusAppDetected)
  944. {
  945. // A modbus application is running on the target
  946. ctx = GfaBlmCtx_ModB;
  947. // Most (but not all) of the commands require the bootloader to be started implicitly, especially when a modbus application is running,
  948. // which is not capable of any command that even a minintet application could handle
  949. if(cla.bUploadImg || cla.bShowDevImgInfo || cla.bValidateImg || cla.bShowMatSer || cla.bSetMatSer)
  950. {
  951. if((nRet = _ModbusStartBootloader(hIf, hBlm, &cla, ctx)) != 0)
  952. break;
  953. ctx = GfaBlmCtx_Boot;
  954. }
  955. else if(!cla.bPing && !cla.bStartBoot) // Ping works with a modbus application as well, so there's no need to start the bootloader.
  956. { // --start-boot is an explicit command on it's own and is handled later.
  957. TRACE2("Nothing to do.\n"); // At this point either a --reset-boot or --revive-boot command was given. Both commands make no sense when any
  958. TTRACE2("Nothing to do"); // kind of application is running, so just exit.
  959. break;
  960. }
  961. }
  962. else
  963. {
  964. // No modbus application was detected, so we are dealing either with a mininet application or the bootloader itself. Find out what ...
  965. TRACE3("Detecting running image.\n");
  966. TTRACE3("Detecting running image");
  967. ctx = GfaBlmGetExecutionContext(hBlm, cla.nNodeAddr);
  968. if((ctx == GfaBlmCtx_Err) || (ctx == GfaBlmCtx_Boot))
  969. {
  970. // Either an error was returned, or the bootloader is running.
  971. // In the latter case, we don't know yet, if it is in a responsive state, because the detection
  972. // involved mininet communication only! We force the bootloader into a working state preventively.
  973. // If the bootloader has already been working correctly, nothing will happen.
  974. if((nRet = _ReviveBootloader(hIf, hBlm, &cla, ctx, true)) != 0)
  975. {
  976. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  977. TTRACE1(GfaTfuStrError(errno));
  978. break;
  979. }
  980. ctx = GfaBlmCtx_Boot;
  981. }
  982. TRACE3("Currently running: %s.\n", (ctx == GfaBlmCtx_App) ? "Application" : "Bootloader");
  983. TTRACE3("Currently running: %s", (ctx == GfaBlmCtx_App) ? "Application" : "Bootloader");
  984. }
  985. // handle the commands
  986. if(cla.bUploadImg)
  987. nRet = _UploadImg(hIf, hBlm, &cla, ctx); // handle --upload-img
  988. else if(cla.bValidateImg)
  989. nRet = _ValidateImg(hIf, hBlm, &cla, ctx); // handle --validate-img
  990. else if(cla.bShowDevImgInfo)
  991. nRet = _ShowDevImgInfo(hIf, hBlm, &cla, ctx); // handle --show-dev-img-info
  992. else if(cla.bShowMatSer)
  993. nRet = _ShowMatSer(hIf, hBlm, &cla, ctx); // handle --show-mat-ser
  994. else if(cla.bSetMatSer)
  995. nRet = _SetMatSer(hIf, hBlm, &cla, ctx); // handle --set-mat-ser
  996. else if(cla.bPing)
  997. nRet = _Ping(hIf, hBlm, &cla, ctx); // handle --ping-target
  998. else if(cla.bStartBoot)
  999. nRet = _StartBootloader(hIf, hBlm, &cla, ctx); // handle --start-boot
  1000. else if(cla.bResetBoot)
  1001. nRet = _ResetBootloader(hIf, hBlm, &cla, ctx); // handle --reset-boot
  1002. else if(cla.bReviveBoot)
  1003. nRet = _ReviveBootloader(hIf, hBlm, &cla, ctx, false); // handle --revive-boot
  1004. }
  1005. else
  1006. { // GfaBlmOpen failed
  1007. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  1008. TTRACE1(GfaTfuStrError(errno));
  1009. break;
  1010. }
  1011. }
  1012. else
  1013. { // GfaSerialGetDeviceInterface failed
  1014. TRACE1("Error: %s!\n", GfaTfuStrError(errno));
  1015. TTRACE1(GfaTfuStrError(errno));
  1016. break;
  1017. }
  1018. }
  1019. while(false);
  1020. if(hBlm)
  1021. {
  1022. TRACE3("Closing bootloader master.\n");
  1023. TTRACE3("Closing bootloader master");
  1024. GfaBlmClose(hBlm);
  1025. }
  1026. if(hIf)
  1027. {
  1028. TRACE3("Closing image file.\n");
  1029. TTRACE3("Closing image file");
  1030. GfaTfuImageFileClose(hIf);
  1031. }
  1032. TTRACEEXIT("%d", nRet);
  1033. return nRet;
  1034. }