UART0 blocks due to UART_S1_TDRE_MASK checking

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

UART0 blocks due to UART_S1_TDRE_MASK checking

2,915 Views
kai_liu
Senior Contributor I

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

Tags (1)
0 Kudos
6 Replies

1,565 Views
donwilley
Contributor II

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?

0 Kudos

1,565 Views
mjbcswitzerland
Specialist V

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:

pastedImage_1.png


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
    }
}
0 Kudos

1,565 Views
kai_liu
Senior Contributor I

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?

1,565 Views
pengliang
Contributor III

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

0 Kudos

1,565 Views
kai_liu
Senior Contributor I

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.

0 Kudos

1,565 Views
kai_liu
Senior Contributor I

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.

0 Kudos