From d080547ccfb05a5e0344289a19c6fbf8bfd202d2 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 8 Jan 2018 22:51:19 +0100 Subject: [PATCH] em9304: upload container blob if HAVE_EM9304_PATCH_CONTAINER --- chipset/em9301/btstack_chipset_em9301.c | 129 +++++++++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/chipset/em9301/btstack_chipset_em9301.c b/chipset/em9301/btstack_chipset_em9301.c index 98a0d5689..8aed4a5c4 100644 --- a/chipset/em9301/btstack_chipset_em9301.c +++ b/chipset/em9301/btstack_chipset_em9301.c @@ -53,9 +53,17 @@ #include /* memcpy */ #include "hci.h" +#include "crc32.h" + // should go to some common place #define OPCODE(ogf, ocf) (ocf | ogf << 10) +#define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27) +#define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28) +#define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29) +#define HCI_OPCODE_EM_CPU_RESET (0xFC32) +#define HCI_OPCODE_EM_PATCH_QUERY (0xFC34) + static const uint32_t baudrates[] = { 0, 0, @@ -74,6 +82,43 @@ static const uint32_t baudrates[] = { 1843200, }; +#if 0 +// crc32 from 802.3 without table lookup to minimize code +uint32_t crc32(const uint8_t *data, uint16_t len) { + int i, j; + uint32_t byte, crc, mask; + crc = 0xFFFFFFFF; + for (i=0;i= 0; j--) { + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + i = i + 1; + } + return ~crc; +} +#endif + +#ifdef HAVE_EM9304_PATCH_CONTAINER + +extern const uint8_t container_blob_data[]; +extern const uint32_t container_blob_size; + +static uint32_t container_blob_offset = 0; +static uint32_t container_end; // current container +static uint16_t patch_sequence_number; +static int em_cpu_reset_sent; + +static enum { + UPLOAD_IDLE, + UPLOAD_ACTIVE, +} upload_state; + +#endif + + static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){ little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x02)); hci_cmd_buffer[2] = 0x06; @@ -84,7 +129,7 @@ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buf // lookup baudrates int i; int found = 0; - for (i=0;i < sizeof(baudrates)/sizeof(uint32_t);i++){ + for (i=0 ; i < sizeof(baudrates)/sizeof(uint32_t) ; i++){ if (baudrates[i] == baudrate){ found = i; break; @@ -99,10 +144,88 @@ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buf hci_cmd_buffer[3] = i; } +#ifdef HAVE_EM9304_PATCH_CONTAINER +static void chipset_init(const void * config){ + UNUSED(config); + container_blob_offset = 0; + em_cpu_reset_sent = 0; + upload_state = UPLOAD_IDLE; +} + +static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){ + log_info("pos %u, container end %u, blob size %u", container_blob_offset, container_end, container_blob_size); + + if (container_blob_offset >= container_blob_size) { + if (0 == em_cpu_reset_sent){ + // send EM CPU Reset + little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET); + hci_cmd_buffer[2] = 0; + em_cpu_reset_sent = 1; + return BTSTACK_CHIPSET_VALID_COMMAND; + } else { + return BTSTACK_CHIPSET_DONE; + } + } + + uint32_t tag; + uint16_t bytes_to_upload; + uint32_t crc; + + switch (upload_state){ + case UPLOAD_IDLE: + // check for 'em93' tag + tag = little_endian_read_32(container_blob_data, container_blob_offset); + if (0x656d3933 != tag) { + log_error("Expected 0x656d3933 ('em934') but got %08x", tag); + return BTSTACK_CHIPSET_DONE; + } + // fetch info for current container + container_end = container_blob_offset + little_endian_read_32(container_blob_data, container_blob_offset + 4); + // start uploading (<= 59 bytes) + patch_sequence_number = 1; + bytes_to_upload = btstack_min(59, container_end - container_blob_offset); + crc = crc32(&container_blob_data[container_blob_offset], bytes_to_upload); + // build command + little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START); + hci_cmd_buffer[2] = 5 + bytes_to_upload; + hci_cmd_buffer[3] = 0; // upload to iRAM1 + little_endian_store_32(hci_cmd_buffer, 4, crc); + memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload); + container_blob_offset += bytes_to_upload; + if (container_blob_offset < container_end){ + upload_state = UPLOAD_ACTIVE; + } + return BTSTACK_CHIPSET_VALID_COMMAND; + case UPLOAD_ACTIVE: + // Upload next segement + bytes_to_upload = btstack_min(58, container_end - container_blob_offset); + crc = crc32(&container_blob_data[container_blob_offset], bytes_to_upload); + // build command + little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE); + hci_cmd_buffer[2] = 6 + bytes_to_upload; + little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++); + little_endian_store_32(hci_cmd_buffer, 5, crc); + memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload); + container_blob_offset += bytes_to_upload; + if (container_blob_offset >= container_end){ + log_info("container done maybe another one"); + upload_state = UPLOAD_IDLE; + } + return BTSTACK_CHIPSET_VALID_COMMAND; + } + return BTSTACK_CHIPSET_DONE; +} +#endif + static const btstack_chipset_t btstack_chipset_em9301 = { "EM9301", - NULL, // chipset_init not used - NULL, // chipset_next_command not used +#ifdef HAVE_EM9304_PATCH_CONTAINER + chipset_init, + chipset_next_command, +#else + NULL, + NULL, +#endif chipset_set_baudrate_command, chipset_set_bd_addr_command, };