I am revising AN4379 bootloader and find some bugs. It is hard to debug step by step, since its interaction between host OS requires real-time tools. UART printf is quite useful. I have tried semihost printf, but it is too slow to print all buffer content.
So I tried my best to add UART0 on FRDM-KL25Z to print some information.
The current situation is: UART0_D can be written once, but I can not find it on my terminal software. Then all the following characters printed are blocked at:
sci.c
uart_putchar()
while(!(UART0_S1 & UART_S1_TDRE_MASK)){}; /*stops here after sending first char*/
UART0_D = (uint_8)ch;
I cross-checked my previous working source for USB host project. The initialization is same.
sci1_init()
SIM_SOPT2 |= SIM_SOPT2_UART0SRC(1);
SIM_SCGC5 |=
PORTA_PCR1 |= PORT_PCR_MUX(0x2);
PORTA_PCR2 |= PORT_PCR_MUX(0x2);
SIM_SCGC4 |= SIM_SCGC4_UART0_MASK;
UART0_C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
UART0_C1 = 0;
ubd = (uint_16)((48000 * 1000)/(UART_BAUDRATE * 16));
UART0_BDH = UART_BDH_SBR(((ubd & 0x1F00) >> 8));
UART0_BDL = (uint_8)(ubd & UART_BDL_SBR_MASK);
UART0_C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK );
How to set UART0_S1_TDRE_MASK to (1) after sending first one?
According to its reference manual, to clear UART0_S1_TDRE, write to UART data register (UART0_D).
0: Transmit data buffer is full
1: Transmit data buffer is empty
More interesting point, when I manually enter characters into UART0_D in register window, they are printed out on terminal window. What's different between manually entering and programmatic way?
Allan K Liu
It seems like this question was not resolved.
Anyone up to try again?
I see this same problem with an MKL16Z4 when I go to do the first ping response in the boot loader.
I tried dropping my baud rate to 9600, but it made no difference.
My call stack looks like:
freedom_bootloader.elf
Thread #1 (Suspended : Signal : SIGINT:Interrupt)
LPSCI_WriteBlocking() at fsl_lpsci.c:527 0x329c
uart0_write() at uart0_peripheral_interface.c:245 0x1188
serial_send_ping_response() at serial_packet.c:346 0x5d8a
read_data_packet.5051() at serial_packet.c:456 0x3d16
serial_packet_read() at serial_packet.c:161 0x5a82
bootloader_command_pump() at bl_command.c:235 0x1f18
bootloader_run() at bl_main.c:897 0xe04
main() at bl_main.c:911 0xe2c
where write blocking code looks like:
void LPSCI_WriteBlocking(UART0_Type *base, const uint8_t *data, size_t length)
{
assert(data);
/* This API can only ensure that the data is written into the data buffer but can't
ensure all data in the data buffer are sent into the transmit shift buffer. */
while (length--)
{
while (!(base->S1 & UART0_S1_TDRE_MASK))
{
}
base->D = *(data++);
}
}
and S1 is always zero.
I examined all the UART0 registers for clues, but it all seems plausible.
base: 0x4006a000
BDH 0
BDL 0x4e
C1 0x0
C2 0x2c
S1 0x0
S2 0x0
C3 0x0
D 0
MA1 0
MA2 0
C5 0
C4 0x1b
Any ideas?
Hello Don
I have attached a binary file for the FRDM-KL26Z which runs KBOOT 2.0.0 on UART0 (as well as USB-MSD [accepts binary and SRECs] and KBOOT HID on USB) - the UART part is the same as for a KL16.
When I look at the UART0 registers when it is connected they are at:
It looks like you may have a missing clock or something for the UART in your case since it looks to be signaling that it is in the process of sending something but never terminates. Your C4 is strange since it is usually 0x0f (16x oversampling) but it may be a typo and not be relevant.
The attached binary was built with the uTasker loader that has ported KBOOT functionality (in combination with various other loader modes that can be used at the same time) to almost all Kinetis parts [http://www.utasker.com/docs/uTasker/uTaskerSerialLoader.pdf]. It is a smaller footprint version using a small OS that makes code much simpler to maintain, customise or extend and allows KBOOT operation to be tested in its Kinetis simulator. Since its drivers automatically match to the part no development/porting work is required when moving between chips types.
Regards
Mark
P.S. Below is also a KBOOT UART + HID protocol implementation showing how easy it actually is in this environment (HW independent and so runs on any Kinetis part)
uTasker developer and supporter (+5'000 hours experience on +60 Kinetis derivatives in +80 product developments)
Kinetis: http://www.utasker.com/kinetis.html
/***********************************************************************
Mark Butcher Bsc (Hons) MPhil MIET
M.J.Butcher Consulting
Birchstrasse 20f, CH-5406, Rütihof
Switzerland
www.uTasker.com Skype: M_J_Butcher
---------------------------------------------------------------------
File: kboot.c
Project: uTasker serial loader
---------------------------------------------------------------------
Copyright (C) M.J.Butcher Consulting 2004..2018
*********************************************************************
*/
/* =================================================================== */
/* include files */
/* =================================================================== */
#include "config.h"
/* =================================================================== */
/* local definitions */
/* =================================================================== */
#define OWN_TASK TASK_APPLICATION
#define STATE_INIT 0x0000 // task states
#define STATE_ACTIVE 0x0001
#define RX_QUEUE_SIZE 256
// HID KBOOT defines
//
#define KBOOT_REPORT_ID_COMMAND_OUT 1
#define KBOOT_REPORT_ID_DATA_OUT 2
#define KBOOT_REPORT_ID_COMMAND_IN 3
#define KBOOT_REPORT_ID_DATA_IN 4
#define KBOOT_COMMAND_TAG_ERASE_ALL 1
#define KBOOT_COMMAND_TAG_ERASE_REGION 2
#define KBOOT_COMMAND_TAG_READ_MEMORY 3
#define KBOOT_COMMAND_TAG_WRITE_MEMORY 4
#define KBOOT_COMMAND_TAG_FILL_MEMORY 5
#define KBOOT_COMMAND_TAG_FLASH_SECURITY_DISABLE 6
#define KBOOT_COMMAND_TAG_GET_PROPERTY 7
#define KBOOT_COMMAND_TAG_RECEIVE_SBFILE 8
#define KBOOT_COMMAND_TAG_EXECUTE 9
#define KBOOT_COMMAND_TAG_CALL 10
#define KBOOT_COMMAND_TAG_RESET 11
#define KBOOT_COMMAND_TAG_SET_PROPERTY 12
#define KBOOT_COMMAND_TAG_MASS_ERASE 13
#define PROPERTY_VERSION 1
#define PROPERTY_PERIPHERALS 2
#define PROPERTY_FLASH_START_ADD 3
#define PROPERTY_FLASH_SIZE_BYTES 4
#define PROPERTY_FLASH_SECTOR_SIZE 5
#define PROPERTY_FLASH_BLOCK_CNT 6
#define PROPERTY_AVAILABLE_CMDS 7
#define PROPERTY_CRC_CHECK_STATUS 8
#define PROPERTY_VERIFY_WRITES 10
#define PROPERTY_MAX_PACKET_SIZE 11
#define PROPERTY_RESERVED_REGIONS 12
#define PROPERTY_VALID_REGIONS 13
#define PROPERTY_RAM_START_ADD 14
#define PROPERTY_RAM_SIZE_BYTES 15
#define PROPERTY_SYS_DEVICE_ID 16
#define PROPERTY_FLASH_SEC_STATE 17
#define PROPERTY_UNIQUE_DEVICE_ID 18
#define KBOOT_SERIAL_START_BYTE 0x5a // 'Z'
#define KBOOT_SERIAL_ACK 0xa1
#define KBOOT_SERIAL_NAK 0xa2
#define KBOOT_SERIAL_ACK_ABORT 0xa3
#define KBOOT_SERIAL_COMMAND 0xa4
#define KBOOT_SERIAL_DATA 0xa5
#define KBOOT_SERIAL_PING 0xa6
#define KBOOT_SERIAL_PING_RESPONSE 0xa7
/* =================================================================== */
/* local structure definitions */
/* =================================================================== */
/* =================================================================== */
/* local function prototype declarations */
/* =================================================================== */
/* =================================================================== */
/* constants */
/* =================================================================== */
const unsigned char ucAck[] = {KBOOT_SERIAL_START_BYTE, KBOOT_SERIAL_ACK};
const unsigned char ucNak[] = {KBOOT_SERIAL_START_BYTE, KBOOT_SERIAL_NAK};
const unsigned char ucPingResponse[] = {KBOOT_SERIAL_START_BYTE, KBOOT_SERIAL_PING_RESPONSE, 0x00, 0x01, 0x01, 'P', 0x00, 0x00, 0x78, 0x04}; // with serial protocol version (P1.1.0)
/* =================================================================== */
/* global variable definitions */
/* =================================================================== */
/* =================================================================== */
/* local variable definitions */
/* =================================================================== */
static unsigned char *ptrFlashAddress = 0;
static unsigned long ulProg_length = 0;
// Application task
//
extern void fnApplication(TTASKTABLE *ptrTaskTable)
{
static int iInputLength = 0;
static QUEUE_HANDLE SerialPortID = NO_ID_ALLOCATED; // serial port handle
static unsigned char ucSerialInputMessage[RX_QUEUE_SIZE] = {0};
static int iAppState = STATE_INIT; // task state
static unsigned char ucInputMessage[HEADER_LENGTH] = {0}; // reserve space for receiving messages (header length used since the serial interface queue is now independent)
QUEUE_HANDLE PortIDInternal = ptrTaskTable->TaskID; // queue ID for task input
if (STATE_INIT == iAppState) {
TTYTABLE tInterfaceParameters; // table for passing information to driver
tInterfaceParameters.Channel = LOADER_UART; // set UART channel for serial use
tInterfaceParameters.ucSpeed = SERIAL_BAUD_57600; // fixed baud rate for kboot compatibility
tInterfaceParameters.Config = (CHAR_8 + NO_PARITY + ONE_STOP + CHAR_MODE); // ensure no XON/XOFF mode used since the transfer is binary
tInterfaceParameters.ucDMAConfig = 0;
tInterfaceParameters.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE; // input buffer size
tInterfaceParameters.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE; // output buffer size
tInterfaceParameters.Task_to_wake = OWN_TASK; // wake self when messages have been received
if ((SerialPortID = fnOpen(TYPE_TTY, FOR_I_O, &tInterfaceParameters)) != NO_ID_ALLOCATED) { // open or change the channel with defined configurations (initially inactive)
fnDriver(SerialPortID, (TX_ON | RX_ON), 0); // enable rx and tx
}
iAppState = STATE_ACTIVE; // move to the active state since initialisation has completed
}
while (fnRead(PortIDInternal, ucInputMessage, HEADER_LENGTH) != 0) { // check task input queue
if (TIMER_EVENT == ucInputMessage[MSG_SOURCE_TASK]) { // timer event
if (T_RESET == ucInputMessage[MSG_TIMER_EVENT]) {
fnResetBoard(); // command hardware reset
}
else if (T_MESSAGE_TIMEOUT == ucInputMessage[MSG_TIMER_EVENT]) { // the start of a message was received but it didn't complete
fnWrite(SerialPortID, (unsigned char *)ucNak, sizeof(ucNak)); // nak the reception
iInputLength = 0; // reset the message
}
else { // assumed - go to application (or T_HOOKUP_TIMEOUT timeout)
fnJumpToValidApplication(1); // if there is a valid application jump to it after disabling used peripherals
iAppState = STATE_ACTIVE; // we return of there is no application
}
}
}
while (fnRead(SerialPortID, &ucSerialInputMessage[iInputLength], 1) != 0) { // check UART input for reception (one byte at a time)
if (iInputLength == 0) { // waiting for the start of a message
if (ucSerialInputMessage[0] == KBOOT_SERIAL_START_BYTE) { // all packets begin with the start byte ('Z')
iInputLength = 1; // start receiving the messaege
uTaskerMonoTimer(OWN_TASK, (DELAY_LIMIT)(0.1 * SEC), T_MESSAGE_TIMEOUT);
}
}
else { // in reception
uTaskerMonoTimer(OWN_TASK, (DELAY_LIMIT)(0.1 * SEC), T_MESSAGE_TIMEOUT);
if (iInputLength == 1) { // command byte
switch (ucSerialInputMessage[1]) {
case KBOOT_SERIAL_PING: // 0xa6:
fnWrite(SerialPortID, (unsigned char *)ucPingResponse, sizeof(ucPingResponse)); // send a ping response back
break;
case KBOOT_SERIAL_DATA: // 0xa5
case KBOOT_SERIAL_COMMAND: // 0xa4:
iInputLength = 2;
continue;
case KBOOT_SERIAL_ACK: // 0xa1:
break;
}
uTaskerStopTimer(OWN_TASK);
iInputLength = 0; // command completed
}
else if (iInputLength == 2) { // expecting command length
// The command length is now in ucSerialInputMessage[2] so the expected length is known
//
iInputLength++;
}
else { // collecting message content
iInputLength++;
if (iInputLength == (ucSerialInputMessage[2] + 6)) { // expected reception complete
unsigned short usCRC = fnCRC16(0, ucSerialInputMessage, 4);
usCRC = fnCRC16(usCRC, &ucSerialInputMessage[6], ucSerialInputMessage[2]);
uTaskerStopTimer(OWN_TASK);
if (usCRC != ((ucSerialInputMessage[5] << 8) | (ucSerialInputMessage[4]))) { // check the CRC of the reception frame
fnWrite(SerialPortID, (unsigned char *)ucNak, sizeof(ucNak)); // nak the reception
}
else {
fnWrite(SerialPortID, (unsigned char *)ucAck, sizeof(ucAck)); // acknowledge the reception
if (ucSerialInputMessage[1] == KBOOT_SERIAL_COMMAND) {
ucSerialInputMessage[2] = KBOOT_REPORT_ID_COMMAND_OUT; // for compatibility
}
else {
ucSerialInputMessage[4] = ucSerialInputMessage[2]; // shift the packet length to where the checksum is (for compatibility)
ucSerialInputMessage[5] = ucSerialInputMessage[3];
ucSerialInputMessage[2] = KBOOT_REPORT_ID_DATA_OUT; // for compatibility
}
if (fnHandleKboot(SerialPortID, KBOOT_UART, (KBOOT_PACKET *)&ucSerialInputMessage[2]) != 0) { // generic kboot handling
uTaskerMonoTimer(OWN_TASK, (DELAY_LIMIT)(1 * SEC), T_RESET);
}
}
iInputLength = 0;
}
}
}
if (iInputLength >= RX_QUEUE_SIZE) { // protect against buffer overflow
iInputLength = 0;
}
}
}
static void fnHandlePropertyGet(unsigned long ulPropertyTag, unsigned long ulMemoryID, KBOOT_PACKET *ptrKBOOT_response)
{
#define BOOT_LOADER_NAME 'K'
#define BOOT_LOADER_MAJOR_VERSION 2
#define BOOT_LOADER_MINOR_VERSION 0
#define BOOT_LOADER_BUGFIX 0
#define kStatus_Success 0
#define kStatus_Fail 1
#define kStatus_ReadOnly 2
#define kStatus_OutOfRange 3
#define kStatus_UnknownProperty 10300
#define kStatus_ReadOnlyProperty 10301
#define kStatus_InvalidPropertyValue 10302
#define KB_SUPPORTS_FLASH_ERASE_ALL 0x00000001
#define KB_SUPPORTS_FLASH_ERASE_REGION 0x00000002
#define KB_SUPPORTS_READ_MEMORY 0x00000004
#define KB_SUPPORTS_WRITE_MEMORY 0x00000008
#define KB_SUPPORTS_FILL_MEMORY 0x00000010
#define KB_SUPPORTS_FLASH_SECURITY_DISABLE 0x00000020
#define KB_SUPPORTS_GET_PROPERTY 0x00000040
#define KB_SUPPORTS_RECEIVE_SB_FILE 0x00000080
#define KB_SUPPORTS_EXECUTE 0x00000100
#define KB_SUPPORTS_CALL 0x00000200
#define KB_SUPPORTS_RESET 0x00000400
#define KB_SUPPORTS_SET_PROPERTY 0x00000800
#define KB_SUPPORTS_FLASH_ERASE_ALL_UNSECURE 0x00001000
#define KB_SUPPORTS_FLASH_PROGRAM_ONCE 0x00002000
#define KB_SUPPORTS_FLASH_READ_ONCE 0x00004000
#define KB_SUPPORTS_FLASH_READ_RESOURCE 0x00008000
#define KB_SUPPORTS_CONFIGURE_QUAD_SPI 0x00010000
#define KB_SUPPORTS_RELIABLE_UPDATE 0x00100000
#define SUPPORTED_KBOOT_COMMANDS (KB_SUPPORTS_FLASH_ERASE_REGION | KB_SUPPORTS_WRITE_MEMORY | KB_SUPPORTS_GET_PROPERTY | KB_SUPPORTS_RESET)
const unsigned long version_info = ((BOOT_LOADER_NAME << 24) | (BOOT_LOADER_MAJOR_VERSION << 16) | (BOOT_LOADER_MINOR_VERSION << 8) | (BOOT_LOADER_BUGFIX));
unsigned long ulStatus = kStatus_Success;
unsigned long ulResponseData[4];
int iDataLength = 1; // most responses return one data value
int iNoStatus = 0;
int iDataIndex = 4;
int iDataRef = 0;
int iDataPairs = 0;
switch (ulPropertyTag) {
case PROPERTY_VERSION: // 1
ulResponseData[0] = (unsigned long)version_info;
break;
case PROPERTY_FLASH_START_ADD: // 3
ulResponseData[0] = FLASH_START_ADDRESS;
break;
case PROPERTY_FLASH_SIZE_BYTES: // 4
ulResponseData[0] = SIZE_OF_FLASH;
break;
case PROPERTY_FLASH_SECTOR_SIZE: // 5
ulResponseData[0] = FLASH_GRANULARITY;
break;
case PROPERTY_AVAILABLE_CMDS: // 7
ulResponseData[0] = SUPPORTED_KBOOT_COMMANDS;
break;
case PROPERTY_RESERVED_REGIONS: // 12 (0x0c)
iNoStatus = 0;
iDataLength = 4; // the number of data values
iDataPairs = 0; // the number of data pairs
ulResponseData[0] = FLASH_START_ADDRESS; // reserved region
ulResponseData[1] = (_UTASKER_APP_START_ - 1);
ulResponseData[2] = RAM_START_ADDRESS;
ulResponseData[3] = (RAM_START_ADDRESS + (SIZE_OF_RAM/2));
break;
case PROPERTY_RAM_SIZE_BYTES: // 15 (0x0f)
ulResponseData[0] = SIZE_OF_RAM;
break;
case PROPERTY_FLASH_SEC_STATE: // 17 (0x11)
#if defined FLASH_CONTROLLER_FTMRE
ulResponseData[0] = ((FTMRH_FSEC & FTMRH_FSEC_SEC_UNSECURE_FLAG) == 0);
#else
ulResponseData[0] = ((FTFL_FSEC & FTFL_FSEC_SEC_UNSECURE) == 0);
#endif
break;
default:
iDataLength = 0;
ulStatus = kStatus_UnknownProperty; // returning this causes an error message to be displayed at the host but further operation is OK
break;
}
if (iNoStatus == 0) { // insert the status if not explicitly not required
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)ulStatus;
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)(ulStatus >> 8);
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)(ulStatus >> 16);
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)(ulStatus >> 24);
ptrKBOOT_response->ucData[3]++; // parameter count
}
while (iDataLength-- != 0) { // insert data
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)ulResponseData[iDataRef];
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)(ulResponseData[iDataRef] >> 8);
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)(ulResponseData[iDataRef] >> 16);
ptrKBOOT_response->ucData[iDataIndex++] = (unsigned char)(ulResponseData[iDataRef] >> 24);
ptrKBOOT_response->ucData[3]++; // parameter count
iDataRef++;
}
while (iDataPairs-- != 0) {
ptrKBOOT_response->ucData[3]--;
}
ptrKBOOT_response->ucLength[0] = (unsigned char)iDataIndex;
}
static void fnReturnResponse(QUEUE_HANDLE hInterface, int iInterfaceType, KBOOT_PACKET *ptrKBOOT_response)
{
if (iInterfaceType == KBOOT_UART) {
unsigned char ucSerialHeader[6];
unsigned short usCRC;
ucSerialHeader[0] = KBOOT_SERIAL_START_BYTE;
ucSerialHeader[1] = KBOOT_SERIAL_COMMAND;
ucSerialHeader[2] = ptrKBOOT_response->ucLength[0];
ucSerialHeader[3] = 0;
usCRC = fnCRC16(fnCRC16(0, ucSerialHeader, (sizeof(ucSerialHeader) - 2)), ptrKBOOT_response->ucData, ptrKBOOT_response->ucLength[0]); // calculate CRC
ucSerialHeader[4] = (unsigned char)usCRC;
ucSerialHeader[5] = (unsigned char)(usCRC >> 8);
fnWrite(hInterface, ucSerialHeader, sizeof(ucSerialHeader)); // send serial header
fnWrite(hInterface, ptrKBOOT_response->ucData, ptrKBOOT_response->ucLength[0]); // send the response body
}
else { // HID
fnWrite(hInterface, (unsigned char *)ptrKBOOT_response, sizeof(KBOOT_PACKET));
}
}
extern int fnHandleKboot(QUEUE_HANDLE hInterface, int iInterfaceType, KBOOT_PACKET *ptrKBOOT_packet)
{
int iReturn = 0;
KBOOT_PACKET KBOOT_response;
uMemset(&KBOOT_response, 0, sizeof(KBOOT_response));
switch (ptrKBOOT_packet->ucCommandType) { // the command
case KBOOT_REPORT_ID_COMMAND_OUT:
KBOOT_response.ucCommandType = KBOOT_REPORT_ID_COMMAND_IN;
switch (ptrKBOOT_packet->ucData[0]) {
case KBOOT_COMMAND_TAG_GET_PROPERTY: // 0x07
{
unsigned long ulPropertyTag = (ptrKBOOT_packet->ucData[4] | (ptrKBOOT_packet->ucData[5] << 8) | (ptrKBOOT_packet->ucData[6] << 16) | (ptrKBOOT_packet->ucData[7] << 24));
unsigned long ulMemoryID = (ptrKBOOT_packet->ucData[8] | (ptrKBOOT_packet->ucData[9] << 8) | (ptrKBOOT_packet->ucData[10] << 16) | (ptrKBOOT_packet->ucData[11] << 24));
KBOOT_response.ucData[0] = (ptrKBOOT_packet->ucData[0] | 0xa0); // response tag
fnHandlePropertyGet(ulPropertyTag, ulMemoryID, &KBOOT_response);
}
break;
case KBOOT_COMMAND_TAG_WRITE_MEMORY: // 0x04
case KBOOT_COMMAND_TAG_ERASE_REGION: // 0x02
{
unsigned long ulStartAddress;
unsigned long ulLength;
ulStartAddress = (ptrKBOOT_packet->ucData[4] | (ptrKBOOT_packet->ucData[5] << 8) | (ptrKBOOT_packet->ucData[6] << 16) | (ptrKBOOT_packet->ucData[7] << 24));
ulLength = (ptrKBOOT_packet->ucData[8] | (ptrKBOOT_packet->ucData[9] << 8) | (ptrKBOOT_packet->ucData[10] << 16) | (ptrKBOOT_packet->ucData[11] << 24));
if (KBOOT_COMMAND_TAG_ERASE_REGION == ptrKBOOT_packet->ucData[0]) { // command to delete an area in flash
if ((ulStartAddress >= UTASKER_APP_START) && (ulStartAddress < (unsigned long)UTASKER_APP_END)) {
if ((ulStartAddress + ulLength) > (unsigned long)UTASKER_APP_END) {
ulLength = ((unsigned long)UTASKER_APP_END - ulStartAddress);
}
fnEraseFlashSector((unsigned char *)ulStartAddress, (MAX_FILE_LENGTH)ulLength);
}
}
else { // command to write following data to flash
ptrFlashAddress = (unsigned char *)ulStartAddress;
ulProg_length = ulLength;
}
KBOOT_response.ucLength[0] = 12; // generic response
KBOOT_response.ucData[0] = 0xa0;
if (iInterfaceType == KBOOT_UART) {
KBOOT_response.ucData[3] = 2;
}
else {
KBOOT_response.ucData[2] = 2;
}
KBOOT_response.ucData[8] = ptrKBOOT_packet->ucData[0];
}
break;
case KBOOT_COMMAND_TAG_RESET: // 0x0b
iReturn = 1; // reset is required
KBOOT_response.ucLength[0] = 12; // generic response
KBOOT_response.ucData[0] = 0xa0;
if (iInterfaceType == KBOOT_UART) {
KBOOT_response.ucData[3] = 2;
fnDriver(hInterface, (RX_OFF), 0); // disable rx since we are resetting (to stop the host's ack triggering receive timer and losing reset timer)
}
else {
KBOOT_response.ucData[2] = 2;
}
KBOOT_response.ucData[8] = ptrKBOOT_packet->ucData[0];
break;
case KBOOT_COMMAND_TAG_ERASE_ALL: // the following are not yet used by KBOOT
case KBOOT_COMMAND_TAG_READ_MEMORY:
case KBOOT_COMMAND_TAG_FILL_MEMORY:
case KBOOT_COMMAND_TAG_FLASH_SECURITY_DISABLE:
case KBOOT_COMMAND_TAG_RECEIVE_SBFILE:
case KBOOT_COMMAND_TAG_EXECUTE:
case KBOOT_COMMAND_TAG_CALL:
case KBOOT_COMMAND_TAG_SET_PROPERTY:
case KBOOT_COMMAND_TAG_MASS_ERASE:
_EXCEPTION("Use detected - investigate....");
break;
}
fnReturnResponse(hInterface, iInterfaceType, &KBOOT_response);
break;
case KBOOT_REPORT_ID_DATA_OUT: // data to be written
{
unsigned short usBuff_length = ptrKBOOT_packet->ucLength[0];
if ((ptrFlashAddress >= (unsigned char *)UTASKER_APP_START) && (ptrFlashAddress < UTASKER_APP_END)) { // if the sector belongs to the application space
if ((ptrFlashAddress + usBuff_length) > UTASKER_APP_END) { // if the write would be past the end of the application space
usBuff_length = (unsigned short)(ptrFlashAddress - UTASKER_APP_END);
}
if (usBuff_length > ulProg_length) {
usBuff_length = (unsigned short)ulProg_length;
}
fnWriteBytesFlash(ptrFlashAddress, ptrKBOOT_packet->ucData, usBuff_length); // program flash
ptrFlashAddress += usBuff_length;
ulProg_length -= usBuff_length;
if (ulProg_length == 0) { // complete code has been received
KBOOT_response.ucCommandType = KBOOT_REPORT_ID_COMMAND_IN;
KBOOT_response.ucLength[0] = 12; // generic response
KBOOT_response.ucData[0] = 0xa0;
if (iInterfaceType == KBOOT_UART) {
KBOOT_response.ucData[3] = 2;
}
else {
KBOOT_response.ucData[2] = 2;
}
KBOOT_response.ucData[8] = KBOOT_COMMAND_TAG_WRITE_MEMORY;
fnWriteBytesFlash(0, 0, 0); // close any outstanding FLASH buffer
fnReturnResponse(hInterface, iInterfaceType, &KBOOT_response); // send response to inform that all data has been programmed
}
}
}
break;
}
return iReturn;
}
// CRC-16 routine
//
extern unsigned short fnCRC16(unsigned short usCRC, unsigned char *ptrInput, unsigned long ulBlockSize)
{
while (ulBlockSize--) {
usCRC = (unsigned char)(usCRC >> 8) | (usCRC << 8);
usCRC ^= *ptrInput++;
usCRC ^= (unsigned char)(usCRC & 0xff) >> 4;
usCRC ^= (usCRC << 8) << 4;
usCRC ^= ((usCRC & 0xff) << 4) << 1;
}
return usCRC;
}
extern void fnJumpToValidApplication(int iResetPeripherals)
{
if ((*(unsigned long *)fnGetFlashAdd((unsigned char *)_UTASKER_APP_START_) != 0xffffffff) && (*(unsigned long *)(fnGetFlashAdd((unsigned char *)_UTASKER_APP_START_) + 4) != 0xffffffff)) {
if (iResetPeripherals != 0) { // if peripherals have been in use
uDisable_Interrupt(); // ensure interrupts are disabled when jumping to the application
#if (defined USB_INTERFACE && defined USB_MSD_HOST_LOADER && defined USB_HOST_SUPPORT)
USB_HOST_POWER_OFF(); // remove power to memory stick
#endif
RESET_PERIPHERALS(); // reset peripherals and disable interrupts ready for jumping to the application
}
#if !defined _WINDOWS
start_application(_UTASKER_APP_START_); // jump to the application
#endif
}
}
// This is called very early on in the board initialisation and can be used to configure hardware.
// - beware that there is no heap available at call time
//
extern void fnUserHWInit(void)
{
if ((FORCE_BOOT() == 0)) {
_DELETE_BOOT_MAILBOX();
fnJumpToValidApplication(0); // {check for forced boot mode or no application code
}
}
I got it.
I changed the sci_init() as following:
//SIM_SOPT2 |= SIM_SOPT2_UART0SRC(1); |
SIM_SOPT2 |= (SIM_SOPT2_UART0SRC(1) | SIM_SOPT2_PLLFLLSEL_MASK);
I found because SIM_SOPT2_PLLFLLSEL_MASK setup will influence UART0_S1_TDRE to 1.
But IRC should be all right for UART0, isn't it?
Hi
how do you solve More interesting point, when I manually enter characters into UART0_D in register window, they are printed out on terminal window. What's different between manually entering and programmatic way?
I wrote code in polling method inside while loop. it is always printed out different chars on terminal windw
Please give some hint
I met similar issue before, I doubt VCP on FRDM have bug on some rate for some chars, like identify 0x00 as 0x80. My solution is changing to slower baudrate. From 115.2Kbps to 57.6Kbps. It dismissed.
Also I do find some threads discussing about UART bugs on silicon. Please search the community.
Or you can give up VCP to route UART to other TTL interface like PL2303/CP2102 to cross check.
I have following code for your reference.
main()
{
sci_init();
printf("balabala"); /*UART not working */
usb_init(); /*PLLFLLSEL is enabled here*/
.... /* where I start to enter data into UART0_D */
}
Because PLLFLLSEL is enabled by USB part. I actually stops after running USB init code, and found manually entering data into UART0_D is working.
Then after several trial, I realized some magic code is inside the USB part, step by step debugging, locate the PLLFLLSEL bit.