#include #include #include #include #include #include #include #include #include "bl_commands.h" #ifdef _TARGET_BUILD #define _DEVICE_NAME "/dev/ttyO4" #else #define _DEVICE_NAME "/dev/tty0" #endif // _TARGET_BUILD #define _SLAVE_NODE_ADDR 0xFF #define _BL_MATERIAL "G.Z.40015 P01" #define _BL_SERIAL "18-080015 1409" // "012345678901234" #define TRACE(...) printf(__VA_ARGS__), fflush(stdout) #if 0 #define TRACE_FRAME(f) GfaMininetMasterDumpFrame(stdout, f) #else #define TRACE_FRAME(f) #endif #define _countof(a) (sizeof(a) / sizeof(*a)) //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// #define GFA_APP_BOOTLOADER_START_ADDRESS ((uint32_t)0x00000000) #define GFA_APP_APPLICATION_START_ADDRESS ((uint32_t)0x00002000) #define GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH 16 // including the zero terminator #define GFA_APP_MAX_IMG_NAME_BUILD_LENGTH 24 // including the zero terminator #define GFA_APP_IMG_HEADER_PREFIX_0 ((uint32_t)0xFF01FF02) #define GFA_APP_IMG_HEADER_PREFIX_1 ((uint32_t)0xFF03FF04) //////////////////////////////////////////////////////////////////////////////////// typedef struct _GFA_APP_IMG_HEADER { const uintptr_t nPrefix0; const uintptr_t nPrefix1; const uintptr_t nImgLength; const uintptr_t nImgCRC32; const uintptr_t nReserved[4]; union { struct { const char * const pszImgMaterialNum; const char * const pszImgNameBuild; }app; struct { const char szImgMaterialNum[GFA_APP_MAX_IMG_MATERIAL_NUM_LENGTH]; const char szImgNameBuild[GFA_APP_MAX_IMG_NAME_BUILD_LENGTH]; }bl; }; }GFA_APP_IMG_HEADER, *LPGFA_APP_IMG_HEADER; typedef const GFA_APP_IMG_HEADER *LPCGFA_APP_IMG_HEADER; //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// static ssize_t _DataPayloadFromMininetFrame(LPCGFA_MININET_FRAME pFrame, void *pData, size_t nCbData) { if(pFrame && pData && nCbData) { if(pFrame->len > 6) { size_t nDatalen = (size_t)pFrame->len - 6; if(nDatalen <= nCbData) { memcpy(pData, &pFrame->data.by[1], nDatalen); return (ssize_t)nDatalen; } } } errno = EINVAL; return -1; } //////////////////////////////////////////////////////////////////////////////////// static ssize_t _PollBlData(HGFAMINEMST hMst, void *pData, size_t nCbData, uint32_t nTimeoutMS) { if(hMst && pData && nCbData) { size_t s, nReceived = 0; struct timeval tvRX; ssize_t nRet = -1; uint8_t cmd[32]; uint8_t txb[32]; uint8_t rxb[512]; uint8_t *pszData = (uint8_t*)pData; tvRX.tv_sec = nTimeoutMS / 1000; tvRX.tv_usec = (nTimeoutMS % 1000) * 1000; GfaMininetMasterSaveTimeouts(hMst); GfaMininetMasterSetTimeouts(hMst, &tvRX, NULL); while(nReceived < nCbData) { s = GfaBLM_BuildCmdDataPacket("BU", NULL, 0, cmd, sizeof(cmd), true); nRet = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, cmd, s, txb, sizeof(txb)); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nRet)) <= 0) { nRet = -1; break; } if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) > 0) { uint8_t nIndex; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); if((nRet = _DataPayloadFromMininetFrame((LPCGFA_MININET_FRAME)rxb, pszData, nCbData - nReceived)) > 0) { pszData += nRet; nReceived += nRet; } } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { TRACE("\nACK ...\n"); } } else { nReceived = nRet; break; } } GfaMininetMasterRestoreTimeouts(hMst); return nReceived; } errno = EINVAL; return -1; } static int _BlPing(HGFAMINEMST hMst) { uint8_t nIndex; ssize_t nRet, nLen; uint8_t nCmd = COMMAND_PING; char txb[32], rxb[32], cmd[8], ack[2]; size_t s = GfaBLM_BuildCmdDataPacket("BU", &nCmd, 1, cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, cmd, s, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) < nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if( (nRet == MINET_SLAVE_RESPONSE_SUCCESS) || (nRet == MINET_SLAVE_RESPONSE_ACK)) { if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); if((nRet = _DataPayloadFromMininetFrame((LPCGFA_MININET_FRAME)rxb, ack, 2)) != 2) return -1; } else { if((nRet = _PollBlData(hMst, ack, 2, 200)) != 2) return -1; } if(ack[0] == 0) { return (ack[1] == COMMAND_ACK); } } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { } return -1; } static int _BlGetStatus(HGFAMINEMST hMst, uint8_t *pbStatus) { uint8_t nIndex; ssize_t nRet, nLen; uint8_t nCmd = COMMAND_GET_STATUS; char txb[32], rxb[32], cmd[8], ack[3], stat[3]; size_t s = GfaBLM_BuildCmdDataPacket("BU", &nCmd, 1, cmd, sizeof(cmd), true); nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, cmd, s, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) < nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if( (nRet == MINET_SLAVE_RESPONSE_SUCCESS) || (nRet == MINET_SLAVE_RESPONSE_ACK)) { if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); if((nRet = _DataPayloadFromMininetFrame((LPCGFA_MININET_FRAME)rxb, ack, 2)) != 2) return -1; } else { if((nRet = _PollBlData(hMst, ack, 2, 200)) != 2) return -1; } if(ack[0] == 0) { if(ack[1] == COMMAND_ACK) { if((nRet = _PollBlData(hMst, stat, 3, 200)) != 3) return -1; if((stat[0] == 3) && (stat[1] == stat[2])) { if(pbStatus) *pbStatus = stat[2]; nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, "BU\xCC", 3, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) <= 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); return 0; } else { } } } } else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE) { // TODO! } return -1; } static int _BlSetBaudrate(HGFAMINEMST hMst, uint32_t nNewBaudrate) { uint8_t nIndex; size_t s; ssize_t nRet, nLen; char txb[32], rxb[32], cmd[8]; uint32_t nBaudrate = bswap_32(nNewBaudrate); s = GfaBLM_BuildCmdDataPacket("BB", &nBaudrate, sizeof(nBaudrate), cmd, sizeof(cmd), false); nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, cmd, s, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_ACK) { GFA_SER_CFG_PARAMS scp; if((nRet = GfaMininetMasterGetConfigParams(hMst, &scp, sizeof(scp))) == sizeof(scp)) { scp.baud = nNewBaudrate; return GfaMininetMasterSetConfigParams(hMst, &scp, sizeof(scp)); } } return -1; } static int _BlDumpMemory(HGFAMINEMST hMst, uint32_t nAddress, uint32_t nCntDwords, void *pBuffer, size_t nCbBuffer) { uint8_t nIndex; size_t s; ssize_t nRet, nLen; char txb[32], rxb[128], cmd[10], dmp[sizeof(uint32_t) * nCntDwords]; if(nCntDwords > 16) nCntDwords = 16; if((nCntDwords * sizeof(uint32_t)) > nCbBuffer) return -1; struct _MEM { uint32_t nAddr; uint32_t nCount; }mem = {bswap_32(nAddress), bswap_32(nCntDwords)}; s = GfaBLM_BuildCmdDataPacket("BD", &mem, sizeof(mem), cmd, sizeof(cmd), false); nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, cmd, s, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); if((nRet = _DataPayloadFromMininetFrame((LPCGFA_MININET_FRAME)rxb, dmp, sizeof(uint32_t) * nCntDwords)) != (ssize_t)(sizeof(uint32_t) * nCntDwords)) return -1; memcpy(pBuffer, dmp, sizeof(uint32_t) * nCntDwords); return 0; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if((nRet = _PollBlData(hMst, dmp, sizeof(uint32_t) * nCntDwords, 200)) != (ssize_t)(sizeof(uint32_t) * nCntDwords)) return -1; memcpy(pBuffer, dmp, sizeof(uint32_t) * nCntDwords); return 0; } return -1; } static int _BlReadMaterialAndSerial(HGFAMINEMST hMst, char *pszMaterial, size_t nCbMaterial, char *pszSerial, size_t nCbSerial) { uint8_t nIndex; ssize_t nRet, nLen; char txb[32], rxb[64], data[32]; if(!pszMaterial || (nCbMaterial < 16) || !pszSerial || (nCbSerial < 16)) return -1; nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, "BR", 2, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); if((nRet = _DataPayloadFromMininetFrame((LPCGFA_MININET_FRAME)rxb, data, sizeof(data))) != sizeof(data)) return -1; memcpy(pszMaterial, data, 16); pszMaterial[15] = '\0'; memcpy(pszSerial, &data[16], 16); pszSerial[15] = '\0'; return 0; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { if((nRet = _PollBlData(hMst, data, sizeof(data), 200)) != (ssize_t)sizeof(data)) return -1; memcpy(pszMaterial, data, 16); pszMaterial[15] = '\0'; memcpy(pszSerial, &data[16], 16); pszSerial[15] = '\0'; return 0; } return -1; } static int _BlWriteMaterialAndSerial(HGFAMINEMST hMst, const char *pszMaterial, const char *pszSerial) { uint8_t nIndex; size_t s; ssize_t nRet, nLen; size_t nLenMaterial, nLenSerial; struct _TS { char szMaterial[16]; char szSerial[16]; }ts; char txb[64], rxb[32], cmd[64]; if(!pszMaterial || !pszSerial) return -1; nLenMaterial = strlen(pszMaterial); nLenSerial = strlen(pszSerial); if((nLenMaterial > 15) || (nLenSerial > 15)) return -1; memcpy(ts.szMaterial, pszMaterial, nLenMaterial); if(nLenMaterial < 15) memset(&ts.szMaterial[nLenMaterial], ' ', 15 - nLenMaterial); ts.szMaterial[15] = '\0'; memcpy(ts.szSerial, pszSerial, nLenSerial); if(nLenSerial < 15) memset(&ts.szSerial[nLenSerial], ' ', 15 - nLenSerial); ts.szSerial[15] = '\0'; s = GfaBLM_BuildCmdDataPacket("BW", &ts, sizeof(ts), cmd, sizeof(cmd), false); nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, cmd, s, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); return 0; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { return 0; } return -1; } static int _BlExecute(HGFAMINEMST hMst) { uint8_t nIndex; ssize_t nRet, nLen; char txb[32], rxb[32]; nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, "BE", 2, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); // TODO: application response } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { return 0; } return -1; } static int _BlIsExecuting(HGFAMINEMST hMst) { uint8_t nIndex; ssize_t nRet, nLen; char txb[32], rxb[32]; nLen = GfaMininetMasterBuildFrame(hMst, _SLAVE_NODE_ADDR, 0, "BU", 2, txb, sizeof(txb)); TRACE_FRAME((LPCGFA_MININET_FRAME)txb); if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) != nLen) return nRet; if((nRet = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) < 0) return nRet; nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, _SLAVE_NODE_ADDR, rxb, nRet, true, &nIndex); if(nRet == MINET_SLAVE_RESPONSE_SUCCESS) { TRACE_FRAME((LPCGFA_MININET_FRAME)rxb); // TODO: application response return 1; } else if(nRet == MINET_SLAVE_RESPONSE_ACK) { return 0; } return -1; } static int _BlGetImgInfo(HGFAMINEMST hMst, uint32_t *pnImgLength, uint32_t *pnImgCRC32) { if(hMst && pnImgLength && pnImgCRC32) { ssize_t nRet = 0; int nDumpIndex = 0; bool bNeedMore; uint32_t i, nDumpAddr, nDumpLen, nBufLen; uint32_t aDump[24] = {0}; for(i = 0; i < 257; i += 16) { nDumpAddr = GFA_APP_BOOTLOADER_START_ADDRESS + i * sizeof(uint32_t); nBufLen = nDumpLen = 16; do { bNeedMore = false; if((nRet = _BlDumpMemory(hMst, nDumpAddr, nDumpLen, &aDump[nDumpIndex], sizeof(aDump) - nDumpIndex * sizeof(uint32_t))) == 0) { uint32_t j; LPCGFA_APP_IMG_HEADER paih; // TRACE("Address: %08X, Length: %2u\n", nDumpAddr, nDumpLen); for(j = nDumpIndex; j < (nDumpLen + nDumpIndex); ++j) { aDump[j] = bswap_32(aDump[j]); } for(j = 0; j < nBufLen; ++j) { paih = (LPCGFA_APP_IMG_HEADER)&aDump[j]; if(paih->nPrefix0 == GFA_APP_IMG_HEADER_PREFIX_0) { if(j < (nBufLen - 1)) { if(paih->nPrefix1 == GFA_APP_IMG_HEADER_PREFIX_1) { if(j < (nBufLen - 3)) { *pnImgLength = paih->nImgLength; *pnImgCRC32 = paih->nImgCRC32; return 0; } else { nDumpAddr += nDumpLen * sizeof(uint32_t); nDumpIndex = nDumpLen; nDumpLen = 2; nBufLen += nDumpLen; bNeedMore = true; break; } } } else { nDumpAddr += nDumpLen * sizeof(uint32_t); nDumpIndex = nDumpLen; nDumpLen = 3; nBufLen += nDumpLen; bNeedMore = true; break; } } } } } while(bNeedMore); } return -1; } errno = EINVAL; return -1; } //////////////////////////////////////////////////////////////////////////////////// int main(void) { ssize_t nRet = 0; //////////////////////////////////////////////////////////////////////////////// GFA_MININET_MST_CFG_PARAMS mmcp; memset(&mmcp, 0, sizeof(mmcp)); if(GfaSerialGetDeviceInterface(&mmcp.devcfg.itf)) { GFA_SER_CFG_PARAMS scp; memset(&scp, 0, sizeof(scp)); //////////////////////////////////////////////////////////////////////////// // serial interface parameters scp.baud = 19200; scp.data = 8; scp.stop = 1; scp.parity = 'N'; #ifdef _TARGET_BUILD scp.bHandleTxEcho = true; #endif // _TARGET_BUILD //////////////////////////////////////////////////////////////////////////// // mininet master configuration mmcp.devcfg.pszDeviceName = _DEVICE_NAME; mmcp.devcfg.pDevParams = &scp; mmcp.devcfg.nSizeDevParams = sizeof(scp); //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// HGFAMINEMST hMst = GfaMininetMasterOpen(&mmcp); if(hMst) { uint8_t status; char szMaterial[16], szSerial[16]; uint32_t nImgLength = 0, nImgCRC32 = 0; if((nRet = GfaMininetMasterResetSlaveIndex(hMst, _SLAVE_NODE_ADDR)) == 0) TRACE("\nReset Slave index.\n"); if((nRet = _BlIsExecuting(hMst)) != 0) { if((nRet = _BlExecute(hMst)) == 0) { TRACE("Executing Bootloader.\n"); if((nRet = GfaMininetMasterResetSlaveIndex(hMst, _SLAVE_NODE_ADDR)) == 0) TRACE("Reset Slave index.\n"); } } else { TRACE("Bootloader is already executing.\n"); } if((nRet = _BlSetBaudrate(hMst, 115200)) == 0) { TRACE("Set Baudrate: %u\n", 115200); } if((nRet = _BlPing(hMst)) == 1) { TRACE("Ping ok!\n"); } if((nRet = _BlGetStatus(hMst, &status)) == 0) { TRACE("Status: 0x%02hhX\n", status); } if((nRet = _BlGetImgInfo(hMst, &nImgLength, &nImgCRC32)) == 0) { TRACE("Bootloader Img. Length: %u, Bootloader Img. CRC: 0x%08X\n", nImgLength, nImgCRC32); } if((nRet = _BlWriteMaterialAndSerial(hMst, "Material 1", "123456789-1")) == 0) { TRACE("Set Material and Serial Numbers ...\n"); } if((nRet = _BlReadMaterialAndSerial(hMst, szMaterial, sizeof(szMaterial), szSerial, sizeof(szSerial))) == 0) { TRACE("Material: \"%s\", Serial: \"%s\"\n", szMaterial, szSerial); } if((nRet = _BlWriteMaterialAndSerial(hMst, _BL_MATERIAL, _BL_SERIAL)) == 0) { TRACE("Set Material and Serial Numbers ...\n"); } if((nRet = _BlReadMaterialAndSerial(hMst, szMaterial, sizeof(szMaterial), szSerial, sizeof(szSerial))) == 0) { TRACE("Material: \"%s\", Serial: \"%s\"\n", szMaterial, szSerial); } if((nRet = _BlSetBaudrate(hMst, 19200)) == 0) { TRACE("Set Baudrate: %u\n", 19200); } if((nRet = _BlPing(hMst)) == 1) { TRACE("Ping ok!\n"); } GfaMininetMasterClose(hMst); } } return nRet; }