Update BM78 EEPROM loading/configuration process. BT security is disabled because that was the only way to get both EDR and LE to work on both Linux and Android at the same time.

cert
Rob Riggs 2018-10-28 20:18:21 -05:00
rodzic 0cd8ebbfd1
commit ffd55e750d
6 zmienionych plików z 373 dodań i 142 usunięć

Wyświetl plik

@ -2,9 +2,11 @@
// All rights reserved.
#include "bm78.h"
#include "bm78_eeprom.hpp"
#include "GPIO.hpp"
#include "Log.h"
#include "main.h"
#include "HdlcFrame.hpp"
#include "stm32l4xx_hal.h"
@ -15,6 +17,7 @@
extern RTC_HandleTypeDef hrtc;
extern UART_HandleTypeDef huart3;
extern CRC_HandleTypeDef hcrc;
namespace mobilinkd { namespace tnc { namespace bm78 {
@ -23,60 +26,47 @@ namespace mobilinkd { namespace tnc { namespace bm78 {
* transparent data transfer in one or both modes. The module documentation
* only clearly describes how to configure the modules using a (horrible)
* Windows application. Microchip publishes a library for use with their
* PIC chips that we use as a guide for implementing our own configuration
* code.
* PIC chips that we initially used as a guide for implementing our own
* configuration code. We now use a hybrid mechanism, writing out the
* entire configuration and tweaking a few settings.
*
* The module must be booted into EEPROM programming mode in order to make
* changes. This mode uses 115200 baud with no hardware flow control
* changes. This mode uses 115200 baud with no hardware flow control.
*
* We program the module for the following features:
*
* - The module is set for 115200 baud with hardware flow control.
* - The name is changed to TNC3.
* - The BT3.0 pairing PIN is set to 1234
* - The BLE5.0 pairing PIN is set to "625653" (MBLNKD on a phone pad).
* - The BLE5.0 pairing PIN is set to "123456".
* - The module power setting is set as low as possible for BLE.
*/
const uint32_t BT_INIT_MAGIC = 0xc0a2;
void bm78_reset()
{
// Must use HAL_Delay() here as osDelay() may not be available.
mobilinkd::tnc::gpio::BT_RESET::off();
HAL_Delay(1200);
HAL_Delay(1);
mobilinkd::tnc::gpio::BT_RESET::on();
HAL_Delay(800);
}
void exit_command_mode()
{
gpio::BT_CMD::on();
bm78_reset();
INFO("BM78 in PASSTHROUGH mode");
}
HAL_StatusTypeDef read_response(uint8_t* buffer, uint16_t size, uint32_t timeout)
{
memset(buffer, 0, size);
auto result = HAL_UART_Receive(&huart3, buffer, size - 1, timeout);
if (result == HAL_TIMEOUT) result = HAL_OK;
return result;
}
bool enter_program_mode()
/**
* Enter BM78 EEPROM programming mode.
*
* This pulls EAN low on the BM78 and resets the module to enter EEPROM
* programming mode and disable HW flow control on the UART.
*
* @note The timing of this process is not well documented.
*/
void enter_program_mode()
{
// Ensure we start out disconnected.
gpio::BT_CMD::off();
HAL_Delay(10);
gpio::BT_RESET::off();
HAL_Delay(10); // Spec says minimum 63ns
HAL_Delay(1); // Spec says minimum 63ns.
gpio::BT_RESET::on();
HAL_Delay(200); // I could not find timing specifications for this.
HAL_Delay(200); // Timing for EEPROM programming is not specified.
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.BaudRate = 115200;
@ -84,95 +74,22 @@ bool enter_program_mode()
{
CxxErrorHandler();
}
// Read (cmd = 0x29) all 1K bytes, starting at address 0, 128 bytes at a time.
uint8_t cmd[] = {0x01, 0x29, 0xfc, 0x03, 0x00, 0x00, 0x80};
constexpr const uint16_t BLOCK_SIZE = 128;
for (uint16_t addr = 0; addr != 0x500; addr += BLOCK_SIZE)
{
cmd[5] = addr & 0xFF;
cmd[4] = (addr >> 8) & 0xFF;
if (HAL_UART_Transmit(&huart3, cmd, sizeof(cmd), 10) != HAL_OK)
{
ERROR("Read EEPROM transmit failed");
return false;
}
uint8_t buffer[BLOCK_SIZE + 10];
if (HAL_UART_Receive(&huart3, buffer, BLOCK_SIZE + 10, 1000) != HAL_OK)
{
ERROR("Read EEPROM receive failed");
return false;
}
for (size_t i = 0; i != BLOCK_SIZE; i += 16) {
printf("%04X: ", addr + i);
for (size_t j = 0; j != 16; j++) {
printf("%02X ", buffer[i + j + 10]);
}
printf("\r\n");
HAL_Delay(10);
}
}
return true;
}
bool exit_program_mode()
/**
* Exit BM78 EEPROM programming mode and return to pass-through mode.
*
* This asserts EAN on the BM78 and resets the module to exit EEPROM
* programming mode, reconfigures the UART for HW flow control, then
* waits for the module to become ready.
*/
void exit_program_mode()
{
auto result = true;
// Read (cmd = 0x29) all 1K bytes, starting at address 0, 128 bytes at a time.
uint8_t cmd[] = {0x01, 0x29, 0xfc, 0x03, 0x00, 0x00, 0x80};
constexpr const uint16_t BLOCK_SIZE = 128;
for (uint16_t addr = 0; addr != 0x500; addr += BLOCK_SIZE)
{
cmd[5] = addr & 0xFF;
cmd[4] = (addr >> 8) & 0xFF;
if (HAL_UART_Transmit(&huart3, cmd, sizeof(cmd), 10) != HAL_OK)
{
ERROR("Read EEPROM transmit failed");
result = false;
break;
}
uint8_t buffer[BLOCK_SIZE + 10];
if (HAL_UART_Receive(&huart3, buffer, BLOCK_SIZE + 10, 1000) != HAL_OK)
{
ERROR("Read EEPROM receive failed");
result = false;
break;
}
for (size_t i = 0; i != BLOCK_SIZE; i += 16) {
printf("%04X: ", addr + i);
for (size_t j = 0; j != 16; j++) {
int c = buffer[i + j + 10];
printf(" %c ", isprint(c) ? (char) c : '.');
}
printf("\r\n");
printf("%04X: ", addr + i);
for (size_t j = 0; j != 16; j++) {
printf("%02X ", buffer[i + j + 10]);
}
printf("\r\n");
HAL_Delay(10);
}
}
// Ensure we start out disconnected.
gpio::BT_CMD::on();
HAL_Delay(10);
gpio::BT_RESET::off();
HAL_Delay(1); // Spec says minimum 63ns.
gpio::BT_RESET::on();
HAL_Delay(400); // Spec says 354ms.
huart3.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
huart3.Init.BaudRate = 115200;
@ -181,21 +98,32 @@ bool exit_program_mode()
CxxErrorHandler();
}
return result;
}
bool set_reset()
{
return true;
bm78_wait_until_ready();
}
/**
* Parse the result of the previous write. Return true if the write was
* successful and false if either the response could not be read or the
* write failed.
*
* @pre A block of EEPROM data was written to the BM78.
* @post The write response has been written.
*
* The result of the write is 7 bytes in length. The write was successful
* if the last byte returned is a 0.
*
* @param function is the name of the calling function and is used when
* logging to indicate which write operation failed.
* @return true when the write was successful, otherwise false.
*/
bool parse_write_result(const char* function)
{
uint8_t result[7];
if (HAL_UART_Receive(&huart3, result, sizeof(result), 1000) != HAL_OK)
HAL_StatusTypeDef status;
if ((status = HAL_UART_Receive(&huart3, result, sizeof(result), 1000)) != HAL_OK)
{
ERROR("%s receive failed", function);
ERROR("%s receive failed (%d)", function, status);
return false;
}
@ -207,7 +135,79 @@ bool parse_write_result(const char* function)
}
return result[6] == 0;
}
/**
* Parse the EEPROM data and write the segments to the BM78 EEPROM.
*
* @pre The BM78 is in programming mode.
* @post The BM78 is programmed.
*
* The data from the EEPROM programming UI is a sparsely populated memory
* map. That data has been converted into <address> <length> <data> format
* in the eeprom_data block. The last block has a zero length, indicating
* EOF. The address is two bytes, big endian, followed by a one byte
* length and *length* bytes of data.
*
* It is important that memory areas that are not populated by the UI are
* not overwritten as they may contain device-specific data elements. For
* example, the first 6 bytes of data are the Bluetooth device MAC address.
*
* The write command is 7 bytes long. The first three bytes are static:
* {0x01, 0x27, 0xfc}. The 4th byte is *length* + 3. The 5th and 6th
* are the address, and the 7th is *length*. The data to be written
* follows.
*
* Once the data has been written, the BM78 module sends a response. This
* must be read and parse before the next block is written.
*
* @return true if the BM78 is programmed, otherwise false.
*/
bool write_eeprom()
{
const uint8_t* data = eeprom_data;
uint8_t cmd[] = {0x01, 0x27, 0xfc, 0x00, 0x00, 0x00, 0x00};
bool result = true;
while (result)
{
auto len = data[2];
cmd[0] = 0x01;
cmd[1] = 0x27;
cmd[2] = 0xfc;
cmd[3] = len + 3;
cmd[4] = data[0];
cmd[5] = data[1];
cmd[6] = len;
if (len == 0)
break;
data += 3;
if (HAL_UART_Transmit(&huart3, cmd, sizeof(cmd), 1000) != HAL_OK)
{
ERROR("%s transmit header failed", __PRETTY_FUNCTION__);
return false;
}
if (HAL_UART_Transmit(&huart3, const_cast<uint8_t*>(data), len, 1000) != HAL_OK)
{
ERROR("%s transmit data failed", __PRETTY_FUNCTION__);
return false;
} else {
DEBUG("%s transmit succeeded %d bytes at 0x%02X%02X",
__FUNCTION__, cmd[6], cmd[4], cmd[5]);
}
result = parse_write_result(__PRETTY_FUNCTION__);
data += len;
}
return result;
}
bool set_name()
@ -331,7 +331,7 @@ bool set_le_attribute_properties()
if (HAL_UART_Transmit(&huart3, cmd, sizeof(cmd), 10) != HAL_OK)
{
ERROR("set_le_attribute_properties transmit failed");
ERROR("%s transmit failed", __PRETTY_FUNCTION__);
return false;
}
@ -429,12 +429,47 @@ bool set_reliable()
}}} // mobilinkd::tnc::bm78
void bm78_wait_until_ready()
{
auto start = HAL_GetTick();
// Must wait until P1_5 (BT_STATE2) is high and P0_4 (BT_STATE1) is low.
GPIO_PinState bt_state1, bt_state2;
do {
if (HAL_GetTick() > start + 2000) CxxErrorHandler(); // Timed out.
HAL_Delay(100);
bt_state2 = HAL_GPIO_ReadPin(BT_STATE2_GPIO_Port, BT_STATE2_Pin);
bt_state1 = HAL_GPIO_ReadPin(BT_STATE1_GPIO_Port, BT_STATE1_Pin);
DEBUG("bt_state2=%d, bt_state1=%d", bt_state2, bt_state1);
} while (!((bt_state2 == GPIO_PIN_SET) and (bt_state1 == GPIO_PIN_RESET)));
}
uint32_t eeprom_crc()
{
const uint8_t* data = eeprom_data;
while (true)
{
data++;
data++;
auto len = *data++;
if (!len) break;
data += len;
}
uint32_t size = data - eeprom_data;
return HAL_CRC_Calculate(&hcrc, (uint32_t*)eeprom_data, size);
}
int bm78_initialized()
{
using namespace mobilinkd::tnc;
using namespace mobilinkd::tnc::bm78;
return HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) == BT_INIT_MAGIC;
auto crc = eeprom_crc();
return HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) == crc;
}
int bm78_initialize()
@ -444,34 +479,18 @@ int bm78_initialize()
int result = 0;
if (!enter_program_mode()) result = 1;
else if (!set_name()) result = 2;
else if (!set_pin()) result = 3;
else if (!set_misc()) result = 4;
else if (!configure_le_service()) result = 5;
enter_program_mode();
if (!write_eeprom()) result = 1;
exit_program_mode();
#if 0
bt_status_init();
if (not enter_command_mode()) result = 1;
else if (not set_uart()) result = 4;
else if (not set_work()) result = 7;
else if (not set_power()) result = 8;
else if (not set_secure()) result = 9;
else if (not set_gpio()) result = 3;
else if (not set_name()) result = 2;
else if (not set_reset()) result = 10;
exit_command_mode();
#if 1
if (result == 0) {
/* Write BT_INIT_MAGIC to RTC back-up register RTC_BKP_DR1 to indicate
that the HC-05 module has been initialized. */
/* Write CRC to RTC back-up register RTC_BKP_DR1 to indicate
that the BM78 module has been initialized. */
HAL_PWR_EnableBkUpAccess();
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, BT_INIT_MAGIC);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, eeprom_crc());
HAL_PWR_DisableBkUpAccess();
}
#endif
#endif
return result;
}

Wyświetl plik

@ -14,6 +14,19 @@ extern "C" {
#include <stdint.h>
#endif
/**
* The BM78 module says that the module is ready about 475ms after start,
* but that the proper thing to do is wait until P1_5 (BT_STATE2) is high
* and P0_4 (BT_STATE1) is low.
*
* This waits for the module to reach this state. If it fails to become
* ready after 2 seconds, it enters the error handler.
*
* @note This does not work to detect whether the module is ready for
* EEPROM programming, only for transparent data mode. The time required
* and state indication for EEPROM programming mode is not specified.
*/
void bm78_wait_until_ready(void);
void bm78_state_change(void);
int bm78_disable(void);
int bm78_enable(void);

106
TNC/bm78_eeprom.cpp 100644
Wyświetl plik

@ -0,0 +1,106 @@
#include "bm78_eeprom.hpp"
const uint8_t eeprom_data[] = {
0x00, 0x07, 0x03, 0x04, 0x04, 0x24, 0x00, 0x0b,
0x10, 0x54, 0x4e, 0x43, 0x33, 0x20, 0x4d, 0x6f,
0x62, 0x69, 0x6c, 0x69, 0x6e, 0x6b, 0x64, 0x00,
0x00, 0x00, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x10,
0x00, 0x31, 0x01, 0x03, 0x00, 0x3b, 0x01, 0x02,
0x00, 0x56, 0x02, 0x11, 0x11, 0x00, 0x5b, 0x10,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xad, 0x06, 0xc1, 0x0c, 0x08, 0x1b, 0x21,
0x00, 0x01, 0xb6, 0x02, 0x03, 0x20, 0x01, 0xba,
0x07, 0x19, 0x00, 0x0c, 0xff, 0xff, 0x01, 0x01,
0x01, 0xc2, 0x02, 0x00, 0x00, 0x01, 0xc5, 0x0b,
0x03, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
0x02, 0x1f, 0x40, 0x01, 0xd4, 0x10, 0xba, 0xb0,
0x00, 0x08, 0x01, 0x90, 0x00, 0x02, 0x02, 0x00,
0x01, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0xe4,
0x02, 0x00, 0x00, 0x01, 0xea, 0x08, 0x1f, 0x18,
0x10, 0x0b, 0x22, 0x05, 0x05, 0x05, 0x01, 0xf3,
0x02, 0x05, 0x05, 0x01, 0xf6, 0x04, 0x00, 0x01,
0x01, 0x01, 0x01, 0xfb, 0x02, 0x02, 0x01, 0x01,
0xfe, 0x04, 0x00, 0x03, 0x02, 0x03, 0x02, 0x03,
0x02, 0x04, 0x02, 0x02, 0x06, 0x04, 0x00, 0x01,
0x03, 0x02, 0x02, 0x0b, 0x02, 0x03, 0x01, 0x02,
0x0e, 0x04, 0x00, 0x3c, 0x1e, 0x1e, 0x02, 0x13,
0x02, 0x1e, 0x1e, 0x02, 0x17, 0x10, 0x0e, 0x4d,
0x6f, 0x62, 0x69, 0x6c, 0x69, 0x6e, 0x6b, 0x64,
0x20, 0x54, 0x4e, 0x43, 0x33, 0x00, 0x02, 0x27,
0x10, 0x00, 0x43, 0x36, 0x50, 0x36, 0x34, 0x4a,
0x32, 0x4d, 0x5a, 0x58, 0x54, 0x4e, 0x43, 0x33,
0x00, 0x02, 0x37, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x42, 0x10, 0x41, 0x42, 0x42, 0x41, 0x41, 0x42,
0x42, 0x41, 0x41, 0x42, 0x42, 0x41, 0x41, 0x42,
0x42, 0x41, 0x02, 0x52, 0x10, 0x00, 0x39, 0x50,
0x56, 0x01, 0x00, 0x00, 0x01, 0x43, 0x68, 0x61,
0x74, 0x62, 0x6f, 0x61, 0x72, 0x02, 0x62, 0x10,
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x49, 0x53,
0x02, 0x72, 0x10, 0x53, 0x43, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x42, 0x4d, 0x02, 0x82, 0x0e, 0x37, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x63,
0x6f, 0x6d, 0x2e, 0x69, 0x73, 0x73, 0x63, 0x2e,
0x64, 0x61, 0x74, 0x61, 0x70, 0x61, 0x74, 0x02,
0xb0, 0x10, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0xc0, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd0, 0x10,
0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x73, 0x73, 0x63,
0x2d, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x00,
0x02, 0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0xf0, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
0x10, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x69, 0x6e,
0x6b, 0x64, 0x20, 0x4c, 0x4c, 0x43, 0x00, 0x00,
0x00, 0x03, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x30, 0x38, 0x36, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x10, 0x54,
0x4e, 0x43, 0x33, 0x00, 0x00, 0x01, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x40, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x50, 0x10,
0x00, 0x00, 0x00, 0x00, 0xbb, 0x68, 0x1f, 0x96,
0xb0, 0x01, 0x49, 0xae, 0xc9, 0x46, 0x2a, 0xba,
0x03, 0x60, 0x10, 0x01, 0x00, 0x00, 0x00, 0xbb,
0x68, 0x1f, 0x96, 0xb0, 0x01, 0x49, 0xae, 0xc9,
0x46, 0x2a, 0xba, 0x03, 0x70, 0x10, 0x03, 0x00,
0x00, 0x00, 0xbb, 0x68, 0x1f, 0x96, 0xb0, 0x01,
0x49, 0xae, 0xc9, 0x46, 0x2a, 0xba, 0x03, 0x80,
0x10, 0x02, 0x00, 0x00, 0x00, 0x10, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x04, 0x03, 0x90, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xa0, 0x10, 0x1b,
0x05, 0x08, 0x54, 0x4e, 0x43, 0x33, 0x11, 0x06,
0xbb, 0x68, 0x1f, 0x96, 0xb0, 0x01, 0x49, 0x03,
0xb0, 0x10, 0xae, 0xc9, 0x46, 0x2a, 0xba, 0x01,
0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x03, 0xc0, 0x10, 0x03, 0x02, 0x0a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd0, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xe0, 0x10, 0x03, 0x02, 0x01, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xf0, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0xf0, 0x10, 0x54, 0x4e, 0x43,
0x33, 0x20, 0x32, 0x2e, 0x31, 0x2e, 0x31, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

Wyświetl plik

@ -0,0 +1,8 @@
// Copyright 2018 Rob Riggs <rob@mobilinkd.com>
// All rights reserved.
#include <cstdint>
extern "C" {
extern const uint8_t eeprom_data[];
}

59
bm78_eeprom 100644
Wyświetl plik

@ -0,0 +1,59 @@
# ADDR1 ADDR2 LEN DATA...
00 07 03 04 04 24 # Class of Device
00 0B 10 54 4E 43 33 20 4D 6F 62 69 6C 69 6E 6B 64 00 00
00 1B 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 2B 01 10
00 31 01 03
00 3B 01 02
00 56 02 11 11
00 5B 10 31 32 33 34 35 36 00 00 00 00 00 00 00 00 00 00
01 AD 06 C1 0C 08 1B 21 00
01 B6 02 03 20
01 BA 07 19 00 0C FF FF 01 01
01 C2 02 00 00
01 C5 0B 03 0C 00 00 08 00 08 00 02 1F 40
01 D4 10 BA B0 00 08 01 90 00 02 02 00 01 00 06 01 03 00
01 E4 02 00 00
01 EA 08 1F 18 10 0B 22 05 05 05
01 F3 02 05 05
01 F6 04 00 01 01 01
01 FB 02 02 01
01 FE 04 00 03 02 03
02 03 02 04 02
02 06 04 00 01 03 02
02 0B 02 03 01
02 0E 04 00 3C 1E 1E
02 13 02 1E 1E
02 17 10 0E 4D 6F 62 69 6C 69 6E 6B 64 20 54 4E 43 33 00
02 27 10 00 43 36 50 36 34 4A 32 4D 5A 58 54 4E 43 33 00
02 37 0B 00 00 00 00 00 00 00 00 00 00 00
02 42 10 41 42 42 41 41 42 42 41 41 42 42 41 41 42 42 41 # Serial Number (can base64 encode the CPUID)
02 52 10 00 39 50 56 01 00 00 01 43 68 61 74 62 6F 61 72
02 62 10 64 00 00 00 00 00 00 00 01 00 00 01 00 00 49 53
02 72 10 53 43 00 00 00 00 00 00 00 00 00 00 00 00 42 4D
02 82 0E 37 38 00 00 00 00 00 00 00 00 00 00 00 00
02 A0 10 63 6F 6D 2E 69 73 73 63 2E 64 61 74 61 70 61 74
02 B0 10 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
02 C0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
02 D0 10 63 6F 6D 2E 69 73 73 63 2D 74 65 63 68 00 00 00
02 E0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
02 F0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 00 10 4D 6F 62 69 6C 69 6E 6B 64 20 4C 4C 43 00 00 00
03 10 10 00 00 00 00 30 38 36 30 00 00 00 00 00 00 00 00
03 20 10 54 4E 43 33 00 00 01 00 04 00 00 00 00 00 00 00
03 30 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 40 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 50 10 00 00 00 00 BB 68 1F 96 B0 01 49 AE C9 46 2A BA
03 60 10 01 00 00 00 BB 68 1F 96 B0 01 49 AE C9 46 2A BA
03 70 10 03 00 00 00 BB 68 1F 96 B0 01 49 AE C9 46 2A BA
03 80 10 02 00 00 00 10 0C 00 00 00 00 00 00 00 01 00 04
03 90 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 A0 10 1B 05 08 54 4E 43 33 11 06 BB 68 1F 96 B0 01 49
03 B0 10 AE C9 46 2A BA 01 00 00 00 02 01 02 00 00 00 00
03 C0 10 03 02 0A 00 00 00 00 00 00 00 00 00 00 00 00 00
03 D0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 E0 10 03 02 01 06 00 00 00 00 00 00 00 00 00 00 00 00
03 F0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
04 00 09 01 00 00 00 00 00 00 00 00
04 F0 10 54 4E 43 33 20 32 2E 31 2E 31 00 00 00 00 00 00
00 00 00

Wyświetl plik

@ -0,0 +1,26 @@
#!/usr/bin/env python
import sys
import re
regex = re.compile("^([0-9A-Fa-f]{2}\s){3}([0-9A-Fa-f]{2}\s?)*(#.*)?$")
bytes = []
for line in sys.stdin:
atoms = re.split("\s+", line)
for atom in atoms:
if len(atom) == 0 or atom == '#':
break
bytes.append(int(atom, 16))
chunks = [bytes[i:i+8] for i in range(0, len(bytes), 8)]
print("#include <cstdint>")
print("const uint8_t eeprom_data[] = {")
for chunk in chunks:
s = ", ".join(['0x{:02x}'.format(x) for x in chunk])
print(" {},".format(s))
print("};")