Files
bootloader/src/blsh/host_command.c
László Monda e6c1fce5b4 Add KBOOT.
2016-08-10 01:45:15 +02:00

1429 lines
51 KiB
C

/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "host_command.h"
#include "host_hardware.h"
#include "microseconds/microseconds.h"
#include "bllibc.h"
#include "bootloader_config.h"
#include "crc/crc16.h"
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief command start. */
static const uint8_t k_commandPing[] = { kFramingPacketStartByte, kFramingPacketType_Ping };
static const uint8_t k_commandAck[] = { kFramingPacketStartByte, kFramingPacketType_Ack };
/* Default transfer bus */
#if BL_CONFIG_SPI
static uint8_t s_current_bus = kSPI_mode;
transfer_data_t write_serial_data = send_spi_data;
transfer_data_t read_serial_data = receive_spi_data;
#elif BL_CONFIG_I2C
static uint8_t s_current_bus = kI2C_mode;
transfer_data_t write_serial_data = send_i2c_data;
transfer_data_t read_serial_data = receive_i2c_data;
#elif BL_CONFIG_UART
static uint8_t s_current_bus = kUART_mode;
transfer_data_t write_serial_data = send_uart_data;
transfer_data_t read_serial_data = receive_uart_data;
#if defined(CPU_MK65FN2M0VMI18)
#elif BL_CONFIG_CAN
static uint8_t s_current_bus = kCAN_mode;
transfer_data_t write_serial_data = send_can_data;
transfer_data_t read_serial_data = receive_can_data;
#endif
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief static local function prototypes
*/
/*! @brief no data phase command protocol process */
static status_t run_noDataPhase_command(command_frame_packet_t *command, void *command_response);
static status_t run_SBfile_command(command_frame_packet_t *command,
generic_response_frame_packet_t *command_response,
uint32_t address);
static status_t run_writeMemory_command(command_frame_packet_t *command,
generic_response_frame_packet_t *command_response,
uint8_t *memory_data);
static status_t run_readMemory_command(command_frame_packet_t *command,
generic_response_frame_packet_t *command_response,
uint8_t *memory_data);
static status_t wait_data_packet(serial_framing_packet_t *data_packet, uint32_t length);
static void read_flash(uint32_t address, uint8_t *buffer, uint32_t bytes);
/*******************************************************************************
* Code
******************************************************************************/
status_t handle_getProperty_command(uint8_t property_tag, uint32_t *response_param)
{
/* Command response */
property_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t getProperty_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
getProperty_command.framing_data.header.startByte = kFramingPacketStartByte;
getProperty_command.framing_data.header.packetType = kFramingPacketType_Command;
getProperty_command.framing_data.length = 0x0c;
getProperty_command.command_data.commandTag = kCommandTag_GetProperty;
getProperty_command.command_data.flags = 0x00;
getProperty_command.command_data.reserved = 0x00;
getProperty_command.command_data.parameterCount = 0x02;
getProperty_command.param[0] = property_tag;
getProperty_command.param[1] = 0;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&getProperty_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&getProperty_command.command_data.commandTag,
getProperty_command.framing_data.length);
getProperty_command.framing_data.crc16 = crc16_value.currentCrc;
/* Handle command */
command_response.generic_response.status = kStatus_Fail;
if (run_noDataPhase_command(&getProperty_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
if (command_response.generic_response.status == kStatus_Success)
{
/* Response result */
response_param[0] = command_response.generic_response.commandPacket.parameterCount;
for (int32_t i = 1; i < response_param[0]; i++)
{
response_param[i] = command_response.generic_response.propertyValue[i - 1];
}
}
return command_response.generic_response.status;
}
status_t handle_setProperty_command(uint8_t property_tag, uint32_t property_value)
{
/* Command response */
property_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t setProperty_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
setProperty_command.framing_data.header.startByte = kFramingPacketStartByte;
setProperty_command.framing_data.header.packetType = kFramingPacketType_Command;
setProperty_command.framing_data.length = 0x0c;
setProperty_command.command_data.commandTag = kCommandTag_SetProperty;
setProperty_command.command_data.flags = 0x00;
setProperty_command.command_data.reserved = 0x00;
setProperty_command.command_data.parameterCount = 0x02;
setProperty_command.param[0] = property_tag;
setProperty_command.param[1] = property_value;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&setProperty_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&setProperty_command.command_data.commandTag,
setProperty_command.framing_data.length);
setProperty_command.framing_data.crc16 = crc16_value.currentCrc;
/* Handle command */
command_response.generic_response.status = kStatus_Fail;
if (run_noDataPhase_command(&setProperty_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.generic_response.status;
}
status_t handle_reset_command(void)
{
/* Command response */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t reset_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
reset_command.framing_data.header.startByte = kFramingPacketStartByte;
reset_command.framing_data.header.packetType = kFramingPacketType_Command;
reset_command.framing_data.length = 0x0004;
reset_command.command_data.commandTag = kCommandTag_Reset;
reset_command.command_data.flags = 0x00;
reset_command.command_data.reserved = 0x00;
reset_command.command_data.parameterCount = 0x00;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&reset_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&reset_command.command_data.commandTag, reset_command.framing_data.length);
reset_command.framing_data.crc16 = crc16_value.currentCrc;
/* Handle command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&reset_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_flashEraseAllUnsecure_command(void)
{
/* Command response */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashEraseAllUnsecure_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
flashEraseAllUnsecure_command.framing_data.header.startByte = kFramingPacketStartByte;
flashEraseAllUnsecure_command.framing_data.header.packetType = kFramingPacketType_Command;
flashEraseAllUnsecure_command.framing_data.length = 0x0004;
flashEraseAllUnsecure_command.command_data.commandTag = kCommandTag_FlashEraseAllUnsecure;
flashEraseAllUnsecure_command.command_data.flags = 0x00;
flashEraseAllUnsecure_command.command_data.reserved = 0x00;
flashEraseAllUnsecure_command.command_data.parameterCount = 0x00;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashEraseAllUnsecure_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashEraseAllUnsecure_command.command_data.commandTag,
flashEraseAllUnsecure_command.framing_data.length);
flashEraseAllUnsecure_command.framing_data.crc16 = crc16_value.currentCrc;
/* Handle command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&flashEraseAllUnsecure_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_flashEraseAll_command(void)
{
/* Command response */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashEraseAll_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
flashEraseAll_command.framing_data.header.startByte = kFramingPacketStartByte;
flashEraseAll_command.framing_data.header.packetType = kFramingPacketType_Command;
flashEraseAll_command.framing_data.length = 0x0004;
flashEraseAll_command.command_data.commandTag = kCommandTag_FlashEraseAll;
flashEraseAll_command.command_data.flags = 0x00;
flashEraseAll_command.command_data.reserved = 0x00;
flashEraseAll_command.command_data.parameterCount = 0x00;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashEraseAll_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashEraseAll_command.command_data.commandTag,
flashEraseAll_command.framing_data.length);
flashEraseAll_command.framing_data.crc16 = crc16_value.currentCrc;
/* Handle command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&flashEraseAll_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_flashEraseRegion_command(uint32_t start_address, uint32_t erase_bytes)
{
/* Command response */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashEraseRegion_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Erase bytes count must be a multiple of 512 */
if (erase_bytes % 512)
{
if (erase_bytes > 512)
{
erase_bytes = ((erase_bytes >> 9) + 1) << 9;
}
else
{
erase_bytes = 512;
}
}
/* Packet */
flashEraseRegion_command.framing_data.header.startByte = kFramingPacketStartByte;
flashEraseRegion_command.framing_data.header.packetType = kFramingPacketType_Command;
flashEraseRegion_command.framing_data.length = 0x000c;
flashEraseRegion_command.command_data.commandTag = kCommandTag_FlashEraseRegion;
flashEraseRegion_command.command_data.flags = 0x00;
flashEraseRegion_command.command_data.reserved = 0x00;
flashEraseRegion_command.command_data.parameterCount = 0x02;
flashEraseRegion_command.param[0] = start_address;
flashEraseRegion_command.param[1] = erase_bytes;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashEraseRegion_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashEraseRegion_command.command_data.commandTag,
flashEraseRegion_command.framing_data.length);
flashEraseRegion_command.framing_data.crc16 = crc16_value.currentCrc;
/* Handle command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&flashEraseRegion_command, &command_response) != kStatus_Success)
{
blsh_printf("\r\n Erase fail!");
return kStatus_Fail;
}
if (command_response.status == kStatus_Success)
{
blsh_printf("\r\n Erase flash region OK! ");
}
else
{
blsh_printf("\r\n Erase fail!");
}
return command_response.status;
}
status_t handle_receiveSBFile_command(uint32_t address, uint32_t length)
{
/* Command response */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t receiveSBFile_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
receiveSBFile_command.framing_data.header.startByte = kFramingPacketStartByte;
receiveSBFile_command.framing_data.header.packetType = kFramingPacketType_Command;
receiveSBFile_command.framing_data.length = 0x0008;
receiveSBFile_command.command_data.commandTag = kCommandTag_ReceiveSbFile;
receiveSBFile_command.command_data.flags = 0x01;
receiveSBFile_command.command_data.reserved = 0x00;
receiveSBFile_command.command_data.parameterCount = 0x01;
receiveSBFile_command.param[0] = length;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&receiveSBFile_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&receiveSBFile_command.command_data.commandTag,
receiveSBFile_command.framing_data.length);
receiveSBFile_command.framing_data.crc16 = crc16_value.currentCrc;
command_response.status = kStatus_Fail;
if (run_SBfile_command(&receiveSBFile_command, &command_response, address) != kStatus_Success)
{
return kStatus_Fail;
}
// return command_response.status;
return kStatus_Success;
}
status_t handle_writeMemory_command(uint32_t start_address, uint8_t *buffer, uint32_t length)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t writeMemory_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
writeMemory_command.framing_data.header.startByte = kFramingPacketStartByte;
writeMemory_command.framing_data.header.packetType = kFramingPacketType_Command;
writeMemory_command.framing_data.length = 0x000c;
writeMemory_command.command_data.commandTag = kCommandTag_WriteMemory;
writeMemory_command.command_data.flags = 0x01;
writeMemory_command.command_data.reserved = 0x00;
writeMemory_command.command_data.parameterCount = 0x02;
writeMemory_command.param[0] = start_address;
writeMemory_command.param[1] = length;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&writeMemory_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&writeMemory_command.command_data.commandTag,
writeMemory_command.framing_data.length);
writeMemory_command.framing_data.crc16 = crc16_value.currentCrc;
/* Flash target */
command_response.status = kStatus_Fail;
if (run_writeMemory_command(&writeMemory_command, &command_response, buffer) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_readMemory_command(uint32_t start_address, uint8_t *buffer, uint32_t length)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t readMemory_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
readMemory_command.framing_data.header.startByte = kFramingPacketStartByte;
readMemory_command.framing_data.header.packetType = kFramingPacketType_Command;
readMemory_command.framing_data.length = 0x000c;
readMemory_command.command_data.commandTag = kCommandTag_ReadMemory;
readMemory_command.command_data.flags = 0x00;
readMemory_command.command_data.reserved = 0x00;
readMemory_command.command_data.parameterCount = 0x02;
readMemory_command.param[0] = start_address;
readMemory_command.param[1] = length;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&readMemory_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&readMemory_command.command_data.commandTag,
readMemory_command.framing_data.length);
readMemory_command.framing_data.crc16 = crc16_value.currentCrc;
/* Read memory */
command_response.status = kStatus_Fail;
if (run_readMemory_command(&readMemory_command, &command_response, buffer) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_fillMemory_command(uint32_t start_address, uint32_t pattern_word, uint32_t byte_count)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t fillMemory_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
fillMemory_command.framing_data.header.startByte = kFramingPacketStartByte;
fillMemory_command.framing_data.header.packetType = kFramingPacketType_Command;
fillMemory_command.framing_data.length = 0x0010;
fillMemory_command.command_data.commandTag = kCommandTag_FillMemory;
fillMemory_command.command_data.flags = 0x00;
fillMemory_command.command_data.reserved = 0x00;
fillMemory_command.command_data.parameterCount = 0x03;
fillMemory_command.param[0] = start_address;
fillMemory_command.param[1] = byte_count;
fillMemory_command.param[2] = pattern_word;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&fillMemory_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&fillMemory_command.command_data.commandTag,
fillMemory_command.framing_data.length);
fillMemory_command.framing_data.crc16 = crc16_value.currentCrc;
/* Execute command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&fillMemory_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_flashSecurityDisable_command(uint32_t backdoorkey_low, uint32_t backdoorkey_high)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashSecurityDisable_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
flashSecurityDisable_command.framing_data.header.startByte = kFramingPacketStartByte;
flashSecurityDisable_command.framing_data.header.packetType = kFramingPacketType_Command;
flashSecurityDisable_command.framing_data.length = 0x000c;
flashSecurityDisable_command.command_data.commandTag = kCommandTag_FlashSecurityDisable;
flashSecurityDisable_command.command_data.flags = 0x00;
flashSecurityDisable_command.command_data.reserved = 0x00;
flashSecurityDisable_command.command_data.parameterCount = 0x02;
flashSecurityDisable_command.param[0] = backdoorkey_low;
flashSecurityDisable_command.param[1] = backdoorkey_high;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashSecurityDisable_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashSecurityDisable_command.command_data.commandTag,
flashSecurityDisable_command.framing_data.length);
flashSecurityDisable_command.framing_data.crc16 = crc16_value.currentCrc;
/* Execute command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&flashSecurityDisable_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_execute_command(uint32_t address, uint32_t arg, uint32_t stack_pointer)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t execute_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
execute_command.framing_data.header.startByte = kFramingPacketStartByte;
execute_command.framing_data.header.packetType = kFramingPacketType_Command;
execute_command.framing_data.length = 0x0010;
execute_command.command_data.commandTag = kCommandTag_Execute;
execute_command.command_data.flags = 0x00;
execute_command.command_data.reserved = 0x00;
execute_command.command_data.parameterCount = 0x03;
execute_command.param[0] = address;
execute_command.param[1] = arg;
execute_command.param[2] = stack_pointer;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&execute_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&execute_command.command_data.commandTag,
execute_command.framing_data.length);
execute_command.framing_data.crc16 = crc16_value.currentCrc;
/* Execute command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&execute_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_call_command(uint32_t address, uint32_t arg)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t call_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
call_command.framing_data.header.startByte = kFramingPacketStartByte;
call_command.framing_data.header.packetType = kFramingPacketType_Command;
call_command.framing_data.length = 0x000c;
call_command.command_data.commandTag = kCommandTag_Call;
call_command.command_data.flags = 0x00;
call_command.command_data.reserved = 0x00;
call_command.command_data.parameterCount = 0x02;
call_command.param[0] = address;
call_command.param[1] = arg;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&call_command.framing_data, sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&call_command.command_data.commandTag, call_command.framing_data.length);
call_command.framing_data.crc16 = crc16_value.currentCrc;
/* Execute command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&call_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_flashProgramOnce_command(uint32_t index, uint32_t byte_count, uint32_t data1, uint32_t data2)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashProgramOnce_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
flashProgramOnce_command.framing_data.header.startByte = kFramingPacketStartByte;
flashProgramOnce_command.framing_data.header.packetType = kFramingPacketType_Command;
flashProgramOnce_command.framing_data.length = (byte_count > 4 ? 0x0014 : 0x0010);
flashProgramOnce_command.command_data.commandTag = kCommandTag_FlashProgramOnce;
flashProgramOnce_command.command_data.flags = 0x00;
flashProgramOnce_command.command_data.reserved = 0x00;
flashProgramOnce_command.command_data.parameterCount = (byte_count > 4 ? 0x04 : 0x03);
flashProgramOnce_command.param[0] = index;
flashProgramOnce_command.param[1] = byte_count;
flashProgramOnce_command.param[2] = data1;
flashProgramOnce_command.param[3] = data2;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashProgramOnce_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashProgramOnce_command.command_data.commandTag,
flashProgramOnce_command.framing_data.length);
flashProgramOnce_command.framing_data.crc16 = crc16_value.currentCrc;
/* Execute command */
command_response.status = kStatus_Fail;
if (run_noDataPhase_command(&flashProgramOnce_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
status_t handle_flashReadOnce_command(uint32_t index, uint32_t byte_count, uint32_t *data1, uint32_t *data2)
{
/* Command response. */
flash_read_once_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashReadOnce_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
flashReadOnce_command.framing_data.header.startByte = kFramingPacketStartByte;
flashReadOnce_command.framing_data.header.packetType = kFramingPacketType_Command;
flashReadOnce_command.framing_data.length = 0x000c;
flashReadOnce_command.command_data.commandTag = kCommandTag_FlashReadOnce;
flashReadOnce_command.command_data.flags = 0x00;
flashReadOnce_command.command_data.reserved = 0x00;
flashReadOnce_command.command_data.parameterCount = 0x02;
flashReadOnce_command.param[0] = index;
flashReadOnce_command.param[1] = byte_count;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashReadOnce_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashReadOnce_command.command_data.commandTag,
flashReadOnce_command.framing_data.length);
flashReadOnce_command.framing_data.crc16 = crc16_value.currentCrc;
/* Execute command */
command_response.response.status = kStatus_Fail;
if (run_noDataPhase_command(&flashReadOnce_command, &command_response) != kStatus_Success)
{
return kStatus_Fail;
}
*data1 = command_response.response.data[0];
*data2 = command_response.response.data[1];
return command_response.response.status;
}
status_t handle_flashReadResource_command(uint32_t start_address, uint8_t *buffer, uint32_t length, uint32_t option)
{
/* Command response. */
generic_response_frame_packet_t command_response;
/* Command packet. */
command_frame_packet_t flashReadResource_command;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Packet */
flashReadResource_command.framing_data.header.startByte = kFramingPacketStartByte;
flashReadResource_command.framing_data.header.packetType = kFramingPacketType_Command;
flashReadResource_command.framing_data.length = 0x0010;
flashReadResource_command.command_data.commandTag = kCommandTag_FlashReadResource;
flashReadResource_command.command_data.flags = 0x00;
flashReadResource_command.command_data.reserved = 0x00;
flashReadResource_command.command_data.parameterCount = 0x03;
flashReadResource_command.param[0] = start_address;
flashReadResource_command.param[1] = length;
flashReadResource_command.param[2] = option;
/* Claulate crc16 value */
crc16_update(&crc16_value, (uint8_t *)&flashReadResource_command.framing_data,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)&flashReadResource_command.command_data.commandTag,
flashReadResource_command.framing_data.length);
flashReadResource_command.framing_data.crc16 = crc16_value.currentCrc;
/* Read memory */
command_response.status = kStatus_Fail;
if (run_readMemory_command(&flashReadResource_command, &command_response, buffer) != kStatus_Success)
{
return kStatus_Fail;
}
return command_response.status;
}
/*!
* @brief no data phase command protocol process.
*
* @param command whole command packet.
* @param command_response command response packet.
*/
static status_t run_noDataPhase_command(command_frame_packet_t *command, void *command_response)
{
int8_t retry = 0;
/* Try ping command with 3 times */
if (wait_ping_response(3) != kStatus_Success)
{
return kStatus_Fail;
}
/* Send command */
write_serial_data((uint8_t *)command, sizeof(framing_data_packet_t) + command->framing_data.length);
blsh_printf("\r\n Inject command '%s'", kCommandNames[command->command_data.commandTag - 1]);
/* Wait for ack packet */
retry = 3;
do
{
if (retry <= 0)
{
return kStatus_Fail;
}
if (wait_ack_packet() == kStatus_Success)
{
break;
}
} while (retry-- > 0);
/* Wait for data response */
wait_command_response(command_response);
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
return kStatus_Success;
}
/*!
* @brief write memory command protocol process.
*
* @param command whole command packet.
* @param command_response command response packet.
* @param memory_data the data written to the memory.
*/
static status_t run_writeMemory_command(command_frame_packet_t *command,
generic_response_frame_packet_t *command_response,
uint8_t *memory_data)
{
uint32_t data_packet_num = 0;
uint32_t data_length = command->param[1];
uint32_t image_index = 0;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Calculate data packet num to send */
if (data_length % kOutgoingPacketBufferSize)
{
data_packet_num = (data_length >> 5) + 1;
}
else
{
data_packet_num = (data_length >> 5);
}
/* Try ping command with 3 times */
if (wait_ping_response(3) != kStatus_Success)
{
return kStatus_Fail;
}
/* Send command */
write_serial_data((uint8_t *)command, sizeof(framing_data_packet_t) + command->framing_data.length);
blsh_printf("\r\n Inject command '%s'", kCommandNames[command->command_data.commandTag - 1]);
/* Wait for ack packet */
if (wait_ack_packet() == kStatus_Fail)
{
return kStatus_Fail;
}
/* Wait for initial response */
wait_command_response(command_response);
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
/* Send Data */
serial_framing_packet_t data_packet;
data_packet.dataPacket.header.startByte = kFramingPacketStartByte;
data_packet.dataPacket.header.packetType = kFramingPacketType_Data;
while (data_packet_num)
{
if (data_length > kOutgoingPacketBufferSize)
{
data_packet.dataPacket.length = kOutgoingPacketBufferSize;
for (int32_t i = 0; i < kOutgoingPacketBufferSize; i++)
{
data_packet.data[i] = memory_data[image_index];
image_index++;
}
data_length -= kOutgoingPacketBufferSize;
}
else
{
data_packet.dataPacket.length = data_length;
for (int32_t i = 0; i < data_length; i++)
{
data_packet.data[i] = memory_data[image_index];
image_index++;
}
data_length = 0;
}
crc16_init(&crc16_value);
crc16_update(&crc16_value, (uint8_t *)&data_packet.dataPacket,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)data_packet.data, data_packet.dataPacket.length);
data_packet.dataPacket.crc16 = crc16_value.currentCrc;
/* Send command */
write_serial_data((uint8_t *)&data_packet, sizeof(framing_data_packet_t) + data_packet.dataPacket.length);
/* Wait for ack packet */
uint8_t retry = 3;
do
{
if (retry <= 0)
{
return kStatus_Fail;
}
if (wait_ack_packet() == kStatus_Success)
{
break;
}
} while (retry-- > 0);
data_packet_num--;
}
/* Wait for final response */
wait_command_response(command_response);
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
return kStatus_Success;
}
/*!
* @brief read memory command protocol process.
*
* @param command whole command packet.
* @param command_response command response packet.
* @param memory_data the data read from memory.
*/
static status_t run_readMemory_command(command_frame_packet_t *command,
generic_response_frame_packet_t *command_response,
uint8_t *memory_data)
{
uint32_t data_packet_num = 0;
uint32_t data_length = command->param[1];
uint32_t image_index = 0;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Calculate data packet num to receive */
if (data_length % kOutgoingPacketBufferSize)
{
data_packet_num = (data_length >> 5) + 1;
}
else
{
data_packet_num = (data_length >> 5);
}
/* Try ping command with 3 times */
if (wait_ping_response(3) != kStatus_Success)
{
return kStatus_Fail;
}
/* Send command */
write_serial_data((uint8_t *)command, sizeof(framing_data_packet_t) + command->framing_data.length);
blsh_printf("\r\n Inject command '%s'", kCommandNames[command->command_data.commandTag - 1]);
/* Wait for ack packet */
if (wait_ack_packet() == kStatus_Fail)
{
return kStatus_Fail;
}
/* Wait for initial response */
wait_command_response(command_response);
if (command_response->status != kStatus_Success)
{
return command_response->status;
}
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
/* Receive Data */
serial_framing_packet_t data_packet = { 0 };
while (data_packet_num)
{
if (data_length > kOutgoingPacketBufferSize)
{
/* Receive data phase packet */
if (wait_data_packet(&data_packet, data_length) != kStatus_Success)
{
return kStatus_Fail;
}
for (int32_t i = 0; i < kOutgoingPacketBufferSize; i++)
{
memory_data[image_index] = data_packet.data[i];
image_index++;
}
data_length -= kOutgoingPacketBufferSize;
}
else
{
/* Receive data phase packet */
if (wait_data_packet(&data_packet, data_length) != kStatus_Success)
{
return kStatus_Fail;
}
for (int32_t i = 0; i < data_length; i++)
{
memory_data[image_index] = data_packet.data[i];
image_index++;
}
data_length = 0;
}
/* Send ack packet */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
data_packet_num--;
}
/* Wait for final response */
wait_command_response(command_response);
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
return kStatus_Success;
}
/*!
* @brief receive sb file command protocol process.
*
* @param command whole command packet.
* @param command_response command response packet.
* @param address the start address of sb image written to the target.
*/
static status_t run_SBfile_command(command_frame_packet_t *command,
generic_response_frame_packet_t *command_response,
uint32_t address)
{
uint32_t data_packet_num = 0;
uint32_t data_length = command->param[0];
int32_t ack_value = 0;
crc16_data_t crc16_value;
crc16_init(&crc16_value);
/* Calculate data packet num to send */
if (data_length % kOutgoingPacketBufferSize)
{
data_packet_num = (data_length >> 5) + 1;
}
else
{
data_packet_num = (data_length >> 5);
}
/* Try ping command with 3 times */
if (wait_ping_response(3) != kStatus_Success)
{
return kStatus_Fail;
}
/* Send command */
write_serial_data((uint8_t *)command, sizeof(framing_data_packet_t) + command->framing_data.length);
blsh_printf("\r\n Inject command '%s'", kCommandNames[command->command_data.commandTag - 1]);
/* Wait for ack packet */
if (wait_ack_packet() == kStatus_Fail)
{
return kStatus_Fail;
}
/* Wait for initial response */
wait_command_response(command_response);
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
/* Send Data */
serial_framing_packet_t data_packet;
data_packet.dataPacket.header.startByte = kFramingPacketStartByte;
data_packet.dataPacket.header.packetType = kFramingPacketType_Data;
while (data_packet_num)
{
if (data_length > kOutgoingPacketBufferSize)
{
data_packet.dataPacket.length = kOutgoingPacketBufferSize;
/* Read data */
read_flash(address, data_packet.data, kOutgoingPacketBufferSize);
data_length -= kOutgoingPacketBufferSize;
address += kOutgoingPacketBufferSize;
}
else
{
data_packet.dataPacket.length = data_length;
/* Read data */
read_flash(address, data_packet.data, data_length);
data_length = 0;
}
crc16_init(&crc16_value);
crc16_update(&crc16_value, (uint8_t *)&data_packet.dataPacket,
sizeof(framing_data_packet_t) - sizeof(uint16_t));
crc16_update(&crc16_value, (uint8_t *)data_packet.data, data_packet.dataPacket.length);
data_packet.dataPacket.crc16 = crc16_value.currentCrc;
/* Send command */
write_serial_data((uint8_t *)&data_packet, sizeof(framing_data_packet_t) + data_packet.dataPacket.length);
/* Wait for ack packet */
uint8_t retry = 3;
do
{
if (retry <= 0)
{
return kStatus_Fail;
}
ack_value = wait_ack_packet();
if ((ack_value == kStatus_Success) || (ack_value == kStatus_OutOfRange))
{
break;
}
} while (retry-- > 0);
/* Finish receive sb file abort unused data */
if (ack_value == kStatus_OutOfRange)
{
break;
}
data_packet_num--;
}
/* Wait for final response */
wait_command_response(command_response);
/* Send ack response */
write_serial_data((uint8_t *)k_commandAck, sizeof(k_commandAck));
return kStatus_Success;
}
/*!
* @brief read flash data.
*
* @param address the start address of reading flash.
* @param buffer the buffer to store flash data.
* @param bytes the number of reading bytes.
*/
static void read_flash(uint32_t address, uint8_t *buffer, uint32_t bytes)
{
for (uint32_t i = 0; i < bytes; i++)
{
*(buffer + i) = *(uint8_t *)address++;
}
}
status_t get_memory_info(memory_info_t *info)
{
uint32_t property_value[4][2] = { 0 };
uint32_t reserved_regions[5] = { 0 };
if (info->is_info_reday == false)
{
/* Get property of memory */
if (handle_getProperty_command(kPropertyTag_FlashStartAddress, property_value[0]) != kStatus_Success)
return kStatus_Fail;
if (handle_getProperty_command(kPropertyTag_FlashSizeInBytes, property_value[1]) != kStatus_Success)
return kStatus_Fail;
if (handle_getProperty_command(kPropertyTag_RAMStartAddress, property_value[2]) != kStatus_Success)
return kStatus_Fail;
if (handle_getProperty_command(kPropertyTag_RAMSizeInBytes, property_value[3]) != kStatus_Success)
return kStatus_Fail;
if (handle_getProperty_command(kPropertyTag_ReservedRegions, reserved_regions) != kStatus_Success)
return kStatus_Fail;
info->flashStart = property_value[0][1];
info->flashSize = property_value[1][1];
info->ramStart = property_value[2][1];
info->ramSize = property_value[3][1];
info->reservedFlashStart = reserved_regions[1];
info->reservedFlashEnd = reserved_regions[2];
info->reservedRamStart = reserved_regions[3];
info->reservedRamEnd = reserved_regions[4];
/* Caluclate the blank area */
info->blankFlashStart =
info->reservedFlashEnd > info->flashStart ? (info->reservedFlashEnd + 1) : (info->flashStart);
info->blankFlashSize = info->flashStart + info->flashSize - info->blankFlashStart;
info->blankRamStart = info->reservedRamEnd > info->ramStart ? (info->reservedRamEnd + 1) : (info->ramStart);
info->blankRamSize = info->ramStart + info->ramSize - info->blankRamStart;
info->is_info_reday = true;
}
return kStatus_Success;
}
status_t get_command_info(command_info_t *info)
{
uint32_t property_value[2] = { 0 };
if (info->is_info_reday == false)
{
if (handle_getProperty_command(kPropertyTag_AvailableCommands, &property_value[0]) != kStatus_Success)
return kStatus_Fail;
info->cmd_mask = property_value[1];
info->is_info_reday = true;
}
return kStatus_Success;
}
void check_transfer_bus(uint8_t transfer_bus, uint32_t *input_freq)
{
uint32_t *freq = input_freq;
if (transfer_bus == kUART_mode)
{
if (*freq < kUART_MIN_BAUD)
{
*freq = kUART_DEFAULT_BAUD;
blsh_printf("\r\n The frequency is adjusted to 19200. ");
}
}
#if defined(CPU_MK65FN2M0VMI18)
else if (transfer_bus == kCAN_mode)
{
if (*freq <= kFLEXCAN_125K)
{
*freq = kFLEXCAN_125K;
blsh_printf("\r\n The frequency is adjusted to 125K. ");
}
else if (*freq <= kFLEXCAN_250K)
{
*freq = kFLEXCAN_250K;
blsh_printf("\r\n The frequency is adjusted to 250K. ");
}
else if (*freq <= kFLEXCAN_500K)
{
*freq = kFLEXCAN_500K;
blsh_printf("\r\n The frequency is adjusted to 500K. ");
}
else
{
*freq = kFLEXCAN_1000K;
blsh_printf("\r\n The frequency is adjusted to 1000K. ");
}
}
#endif
}
void configure_transfer_bus(uint8_t transfer_bus, uint32_t freq)
{
if ((s_current_bus != transfer_bus) || (s_current_bus == kUART_mode))
{
s_current_bus = transfer_bus;
if (handle_reset_command() == kStatus_Success)
{
blsh_printf("\r\n The target has reset successfully. ");
}
else
{
blsh_printf("\r\n Reset fail");
}
}
if (transfer_bus == kSPI_mode)
{
write_serial_data = send_spi_data;
read_serial_data = receive_spi_data;
configure_spi_speed(freq);
}
else if (transfer_bus == kI2C_mode)
{
write_serial_data = send_i2c_data;
read_serial_data = receive_i2c_data;
configure_i2c_speed(freq);
}
else if (transfer_bus == kUART_mode)
{
write_serial_data = send_uart_data;
read_serial_data = receive_uart_data;
configure_uart_speed(freq);
}
#if defined(CPU_MK65FN2M0VMI18)
else if (transfer_bus == kCAN_mode)
{
write_serial_data = send_can_data;
read_serial_data = receive_can_data;
configure_can_speed(freq);
}
#endif
}
status_t run_ping_command(void)
{
uint8_t data[10] = { 0 };
uint8_t recvStart = 0;
uint8_t packetType = 0;
uint64_t timeoutTicks = microseconds_get_ticks() + microseconds_convert_to_ticks(2000000); /* 2s time out */
write_serial_data((uint8_t *)k_commandPing, sizeof(k_commandPing));
/* Wait start byte response */
microseconds_delay(100);
while ((recvStart != kFramingPacketStartByte) && (microseconds_get_ticks() < timeoutTicks))
{
read_serial_data(&recvStart, 1);
}
if (recvStart != kFramingPacketStartByte)
{
return kStatus_Fail;
}
read_serial_data(&packetType, 1);
if (packetType != kFramingPacketType_PingResponse)
{
return kStatus_Fail;
}
read_serial_data(data, 8);
return kStatus_Success;
}
status_t wait_ping_response(uint8_t try_count)
{
for (uint8_t i = 1; i <= try_count; i++)
{
if (run_ping_command() == kStatus_Success)
{
blsh_printf("\r\n Ping responded in %d attempt(s)", i);
return kStatus_Success;
}
}
blsh_printf("\r\n Error: Initial ping failure: No response received for ping command");
return kStatus_Fail;
}
status_t wait_ack_packet(void)
{
uint8_t recvStart = 0;
uint8_t packetType = 0;
uint64_t timeoutTicks = microseconds_get_ticks() + microseconds_convert_to_ticks(5000000); /* 5s time out */
/* Wait start byte response */
microseconds_delay(100);
while ((recvStart != kFramingPacketStartByte) && (microseconds_get_ticks() < timeoutTicks))
{
read_serial_data(&recvStart, 1);
}
if (recvStart != kFramingPacketStartByte)
{
return kStatus_Fail;
}
read_serial_data(&packetType, 1);
if (packetType == kFramingPacketType_Ack)
{
return kStatus_Success;
}
else if (packetType == kFramingPacketType_AckAbort)
{
return kStatus_OutOfRange;
}
else if (packetType == kFramingPacketType_Nak)
{
return kStatus_Fail;
}
else
{
return kStatus_Fail;
}
}
status_t wait_command_response(generic_response_frame_packet_t *command_response)
{
uint16_t length_rev = 0;
uint16_t crc_rev = 0;
uint8_t recvStart = 0;
uint8_t packetType = 0;
uint64_t timeoutTicks = microseconds_get_ticks() + microseconds_convert_to_ticks(5000000); /* 5s time out */
/* Wait start byte response */
microseconds_delay(100);
while ((recvStart != kFramingPacketStartByte) && (microseconds_get_ticks() < timeoutTicks))
{
read_serial_data(&recvStart, 1);
}
if (recvStart != kFramingPacketStartByte)
{
return kStatus_Fail;
}
read_serial_data(&packetType, 1);
if (packetType == kFramingPacketType_Command)
{
read_serial_data((uint8_t *)&length_rev, sizeof(uint16_t));
read_serial_data((uint8_t *)&crc_rev, sizeof(uint16_t));
command_response->framing_data.header.startByte = kFramingPacketStartByte;
command_response->framing_data.header.packetType = kFramingPacketType_Command;
command_response->framing_data.length = length_rev;
command_response->framing_data.crc16 = crc_rev;
read_serial_data((uint8_t *)&command_response->commandTag, command_response->framing_data.length);
return kStatus_Success;
}
else
{
return kStatus_Fail;
}
}
/*!
* @brief wait data packet when read memory.
*
* @param data_packet data packet for store memory data.
* @param length the length to read.
* @return status_t the status value
*/
static status_t wait_data_packet(serial_framing_packet_t *data_packet, uint32_t length)
{
uint16_t length_rev = 0;
uint16_t crc_rev = 0;
uint8_t recvStart = 0;
uint8_t packetType = 0;
uint64_t timeoutTicks = microseconds_get_ticks() + microseconds_convert_to_ticks(5000000); /* 5s time out */
/* Wait start byte response */
microseconds_delay(100);
while ((recvStart != kFramingPacketStartByte) && (microseconds_get_ticks() < timeoutTicks))
{
read_serial_data(&recvStart, 1);
}
if (recvStart != kFramingPacketStartByte)
{
return kStatus_Fail;
}
read_serial_data(&packetType, 1);
/* Receive data phase packet */
if (packetType == kFramingPacketType_Data)
{
read_serial_data((uint8_t *)&length_rev, sizeof(uint16_t));
read_serial_data((uint8_t *)&crc_rev, sizeof(uint16_t));
data_packet->dataPacket.header.startByte = kFramingPacketStartByte;
data_packet->dataPacket.header.packetType = kFramingPacketType_Data;
data_packet->dataPacket.length = length_rev;
data_packet->dataPacket.crc16 = crc_rev;
read_serial_data((uint8_t *)&data_packet->data, length);
return kStatus_Success;
}
else
{
return kStatus_Fail;
}
}