MKE1xF ROM Bootloader with CAN

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

MKE1xF ROM Bootloader with CAN

Jump to solution
1,432 Views
callendorph
Contributor I

Hi, 

We're using an KE16F microcontroller in our application. I want to use the CAN interface to the ROM bootloader. I'm looking at the reference manual here:

https://www.nxp.com/docs/en/reference-manual/KE1xFP100M168SF0RM.pdf


Chapter 23 Discusses the ROM bootloader and its features. 

I'm attempting to access the ROM bootloader via the CAN interface. We're using a custom board for which we have already thoroughly validated the hardware (CAN interface is known working from application code). 

I'm attempting to configure the bootloader with the following settings:

Bitrate: 125kHz
Tx Id : 0x270  ( bootloader sends response messages to this id)
Rx Id : 0x269  ( bootloader receives command messages on this id)


I've left the "Flash Config" settings as default:

__attribute__ ((used,section(".FlashConfig"))) const struct {
unsigned int word1;
unsigned int word2;
unsigned int word3;
unsigned int word4;
} Flash_Config = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF7DFE};

FLOPT = 0x7D which I believe indicates that we will enter the bootloader is the NMI pin is held low.


I've confirmed that I can enter the bootloader by asserting the NMI (pulling it low) and pressing the reset button. I've checked that the processor is operating from the ROM memory space by attaching a J-Link debugger. 

I've downloaded the KinetisFlashTool to generate the BCA for our device. I used the following settings: 

typedef struct BootloaderConfiguration
{
uint32_t tag; //!< [00:03] Magic number to verify bootloader configuration is
//! valid. Must be set to 'kcfg'.
uint32_t crcStartAddress; //!< [04:07] Start address for application image CRC
//! check. If the bits are all set then Kinetis
//! bootloader by default will not perform any CRC
//! check.
uint32_t crcByteCount; //!< [08:0b] Byte count for application image CRC
//! check. If the bits are all set then Kinetis
//! bootloader by default will not prform any CRC check.
uint32_t crcExpectedValue; //!< [0c:0f] Expected CRC value for application CRC
//! check. If the bits are all set then Kinetis
//! bootloader by default will not perform any CRC
//! check.
uint8_t enabledPeripherals; //!< [10:10] Bitfield of peripherals to enable.
//! bit 0 - LPUART, bit 1 - I2C, bit 2 - SPI,
//! bit 3 - CAN, bit 4 - USB
//! Kinetis bootloader will enable the peripheral if
//! corresponding bit is set to 1.
uint8_t i2cSlaveAddress; //!< [11:11] If not 0xFF, used as the 7-bit I2C slave
//! address. If 0xFF, defaults to 0x10
//! for I2C slave address.
uint16_t peripheralDetectionTimeoutMs; //!< [12:13] Timeout in milliseconds
//! for active peripheral detection. If
//! 0xFFFF, defaults to 5 seconds.
uint16_t usbVid; //!< [14:15] Sets the USB Vendor ID reported by the device
//! during enumeration. If 0xFFFF, it defaults to 0x15A2.
uint16_t usbPid; //!< [16:17] Sets the USB Product ID reported by the device
//! during enumeration.
uint32_t usbStringsPointer; //!< [18:1b] Sets the USB Strings reported by the
//! device during enumeration.
uint8_t clockFlags; //!< [1c:1c] The flags in the clockFlags configuration
//! field are enabled if the corresponding bit is cleared (0).
//! bit 0 - HighSpeed Enable high speed mode (i.e., 48 MHz).
uint8_t clockDivider; //!< [1d:1d] Inverted value of the divider to use for
//! core and bus clocks when in high speed mode.
uint8_t bootFlags; //!< [1e:1e] If bit 0 is cleared, then Kinetis bootloader
//! will jump to either Quad SPI Flash or internal flash
//! image depending on FOPT BOOTSRC_SEL bits.
//! If the bit is set, then Kinetis bootloader will prepare
//! for host communication over serial peripherals.
uint8_t pad0; //!< [1f:1f] Reserved, set to 0xFF
uint32_t mmcauConfigPointer; //!< [20:23] A pointer to the MMCAU configuration
//! structure in memory.
uint32_t keyBlobPointer; //!< [24:27]Holds a pointer value to the key blob
//! array used to configure OTFAD
uint8_t pad1; //!< [28:28] reserved
uint8_t canConfig1; //!< [29:29] ClkSel[1], PropSeg[3], SpeedIndex[4]
uint16_t canConfig2; //!< [2a:2b] Pdiv[8], Pseg1[3], Pseg2[3], rjw[2]
uint16_t canTxId; //!< [2c:2d] txId
uint16_t canRxId; //!< [2e:2f] rxId
uint32_t qspi_config_block_pointer; //!< [30:33] A pointer to the QSPI config
//! block in internal flash array.
uint32_t reserved[3]; //!<[34:3f] reserved
} bootloader_config_t;


__attribute__((section(".BootConfigArea"))) const bootloader_config_t BootloaderConfig = {
.tag = 0x6766636B, //!< Magic Number
.crcStartAddress = 0xFFFFFFFF, //!< Disable CRC check
.crcByteCount = 0xFFFFFFFF, //!< Disable CRC check
.crcExpectedValue = 0xFFFFFFFF, //!< Disable CRC check
.enabledPeripherals = 0xE8, //!< Enabled Peripheral: CAN
.i2cSlaveAddress = 0xFF, //!< Use default I2C address(0x10)
.peripheralDetectionTimeoutMs = 0xFFFF, //!< Use default timeout(5000ms)
.usbVid = 0xFFFF, //!< Use default Vendor ID(0x15A2)
.usbPid = 0xFFFF, //!< Use default Product ID(0x0073)
.usbStringsPointer = 0xFFFFFFFF, //!< Use default USB String
.clockFlags = 0xFE, //!< Enable High speed mode
.clockDivider = 0xFE, //!< Use clock divider(1)
.bootFlags = 0xFF, //!< Enable communication with host
.mmcauConfigPointer = 0xFFFFFFFF, //!< No MMCAU configuration
.keyBlobPointer = 0xFFFFFFFF, //!< No key blob
.canConfig1 = 0xF0, //!< Use user-defined canConfig1
.canConfig2 = 0xFFFF, //!< Use default canConfig2
.canTxId = 0x0270, //!< Use user-defined CAN TX ID
.canRxId = 0x0269, //!< Use user-defined CAN RX ID
.qspi_config_block_pointer = 0xFFFFFFFF, //!< No QSPI configuration
};

I've attempted to select 125kHz bitrate with no auto-detect. I've additionally attempting to set the transmit and receive IDs per my specifications. 

I configure the linker to write this object to `0x3C0`. When I program the device, I can confirm that the memory space is written with my BCA configs: 

0x000003A8 FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿ
0x000003B0 FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿ
0x000003B8 FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿ
0x000003C0 6766636B FFFFFFFF kcfgÿÿÿÿ
0x000003C8 FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿ
0x000003D0 FFFFFFE8 FFFFFFFF èÿÿÿÿÿÿÿ
0x000003D8 FFFFFFFF 00FFFEFE ÿÿÿÿþþÿ.
0x000003E0 FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿ
0x000003E8 FFFFF000 02690270 .ðÿÿp.i.
0x000003F0 FFFFFFFF 00000000 ÿÿÿÿ....
0x000003F8 00000000 00000000 ........
0x00000400 FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿ
0x00000408 FFFFFFFF FFFF7DFE ÿÿÿÿþ}ÿÿ
0x00000410 AF00B580 FCDDF001 .µ.¯.ðÝü
0x00000418 FCC8F001 FCD3F001 .ðÈü.ðÓü


I then disconnect the debugger, assert the NMI, and then reboot the chip. My CAN bus is setup to use a PEAK PCAN-USB. At first, I didn't have any other devices on the bus but because the bootloader wasn't responding, the PEAK repeatedly tries to send messages that are never ack'd. I then added another device on the bus whose sole job is to just ack packets. 

When I attempt to communicate with the bootloader I send the following: 

```

$> sudo ip link set can0 up type can bitrate 125000
$> cansend can0 269#5AA6
```

Per section 23.3.7.1 - this should be a ping packet. 

In candump I see this message show up: 

```

(1678900939.289388) can0 269 [2] 5A A6

```

I've confirmed with an oscilloscope that I see the CAN bus message show up when the PEAK sends it. 

I see no response on the CAN bus from the MKE16F. I've also tried sending to the following addresses:

0x270 - just in case they are backwards
0x00000269 - Extended Address 
0x00000270


None of these elicit a response from the bootloader. 

I'm assuming that I'm doing something wrong with the configuration. Can anyone tell me what I'm doing wrong ? 

 

0 Kudos
1 Solution
1,285 Views
andresvg
Contributor I

Hi, this is how I was able to make 125 KHz work, it may be specific to our custom board based on KE16F but may be useful to someone else, so sharing it here.

Some initial facts:

  • MCU boot loader version: 1.5.1
  • Source code looked at, boot loader versions 1.2.0 and 2.0.0
  • The handling of BCA parameters for CAN bus timing in boot loader code 1.2.0 and 2.0.0 are identical.
  • Using tool KinetisFlashTool.exe from boot loader source code 2.0.0

The following information allowed me to define proper CAN bus timing parameters:

  1. In tool KinetisFlashTool, check "Disable Detection", "Specify" and "Enable High Speed" to define your own CAN timing configuration.
  2. In calculating the pre-scaler divider, assume 24 MHz (instead of 48 MHz).
  3. Select the timing parameters PRESDIV, RJW, PSEG1, PSEG2, and PROPSEG  that you need, and subtract 1 from them and the resulting values set in KinetisFlashTool (this is explained in the MCU reference manual).

E.g. to configure CAN bus for 125 KHz

For our timing, let's select (in clock cycles after the pre-scaled divider):

Sync segment (always 1) + PSEG1 (4) + PSEG2 (4) + PROPSEG (3) = 12 cycles

Such that 24MHz / 12 = 2 MHz

Then 2 MHz / 125 KHz =16 = PREDIV

Apply the above parameters in KinetisFlashTool.exe (remember the -1): PREDIV=0x0F, PSEG1=0x3, PSEG2=0x3, RJW=0x3 and PROPSEG=0x2 and generate C code.

The resulting code will include this line that needs to change:

 

.canConfig1 = 0xAF, //!< Use user-defined canConfig1

 


Now manually change to the following, before using it to store that in BCA area:

 

.canConfig1 = 0xA8, //!< Use user-defined canConfig1

 

This is the portion of CAN boot loader code (file `flexcan_peripheral_interface.c`) to look at to understand why 0xF doesn't work and why changing it to 0x8 make the parameters you set to actually be used to configure CAN peripheral:

 

#define FLEXCAN_SPEED_MASK 0x0F
#define FLEXCAN_SPEED_SPEC_MASK 0x08
 
    // check baud rate config
    if ((canConfig1 & FLEXCAN_SPEED_MASK) == 0x0f)
    {
        // not specified, go with auto detection feature enabled
        s_flexcanInfo.baudrateDetect = true;

        // select default baud rate 1M
        s_flexcanInfo.baudrate = FLEXCAN_MAX_SPEED - 1;
    }
    else
    {
        // baud rate config specified
        s_flexcanInfo.baudrateDetect = false;

        if (canConfig1 & FLEXCAN_SPEED_SPEC_MASK)
        {
            // specified baud rate setting directly
            s_flexcanInfo.baudrate = FLEXCAN_MAX_SPEED;

            // get config data from BCA area
            canConfig2 = g_bootloaderContext.propertyInterface->store->configurationData.canConfig2;

            // prepare specified config data
            bit_rate_table1.pre_divider = (canConfig2 & FLEXCAN_PRESCALER_MASK) >> FLEXCAN_PRESCALER_SHIFT;
            bit_rate_table1.pseg1 = (canConfig2 & FLEXCAN_PSEG1_MASK) >> FLEXCAN_PSEG1_SHIFT;
            bit_rate_table1.pseg2 = (canConfig2 & FLEXCAN_PSEG2_MASK) >> FLEXCAN_PSEG2_SHIFT;
            bit_rate_table1.rjw = canConfig2 & FLEXCAN_RJW_MASK;
            bit_rate_table1.propseg = (canConfig1 & FLEXCAN_PROPSEG_MASK) >> FLEXCAN_PROPSEG_SHIFT;
        }
        else
        {
            // specified speed index, baud rate settings from bootloader
            s_flexcanInfo.baudrate = canConfig1 & FLEXCAN_SPEED_INDEX_MASK;

            if (s_flexcanInfo.baudrate >= FLEXCAN_MAX_SPEED)
            {
                s_flexcanInfo.baudrate = FLEXCAN_MAX_SPEED - 1;
            }
        }
    }

 

 This is how the tool KinetisFlashTool.exe looked like after selecting the parameters I wanted:
KinetisFlashTool-CAN-125KHz.png

View solution in original post

3 Replies
1,286 Views
andresvg
Contributor I

Hi, this is how I was able to make 125 KHz work, it may be specific to our custom board based on KE16F but may be useful to someone else, so sharing it here.

Some initial facts:

  • MCU boot loader version: 1.5.1
  • Source code looked at, boot loader versions 1.2.0 and 2.0.0
  • The handling of BCA parameters for CAN bus timing in boot loader code 1.2.0 and 2.0.0 are identical.
  • Using tool KinetisFlashTool.exe from boot loader source code 2.0.0

The following information allowed me to define proper CAN bus timing parameters:

  1. In tool KinetisFlashTool, check "Disable Detection", "Specify" and "Enable High Speed" to define your own CAN timing configuration.
  2. In calculating the pre-scaler divider, assume 24 MHz (instead of 48 MHz).
  3. Select the timing parameters PRESDIV, RJW, PSEG1, PSEG2, and PROPSEG  that you need, and subtract 1 from them and the resulting values set in KinetisFlashTool (this is explained in the MCU reference manual).

E.g. to configure CAN bus for 125 KHz

For our timing, let's select (in clock cycles after the pre-scaled divider):

Sync segment (always 1) + PSEG1 (4) + PSEG2 (4) + PROPSEG (3) = 12 cycles

Such that 24MHz / 12 = 2 MHz

Then 2 MHz / 125 KHz =16 = PREDIV

Apply the above parameters in KinetisFlashTool.exe (remember the -1): PREDIV=0x0F, PSEG1=0x3, PSEG2=0x3, RJW=0x3 and PROPSEG=0x2 and generate C code.

The resulting code will include this line that needs to change:

 

.canConfig1 = 0xAF, //!< Use user-defined canConfig1

 


Now manually change to the following, before using it to store that in BCA area:

 

.canConfig1 = 0xA8, //!< Use user-defined canConfig1

 

This is the portion of CAN boot loader code (file `flexcan_peripheral_interface.c`) to look at to understand why 0xF doesn't work and why changing it to 0x8 make the parameters you set to actually be used to configure CAN peripheral:

 

#define FLEXCAN_SPEED_MASK 0x0F
#define FLEXCAN_SPEED_SPEC_MASK 0x08
 
    // check baud rate config
    if ((canConfig1 & FLEXCAN_SPEED_MASK) == 0x0f)
    {
        // not specified, go with auto detection feature enabled
        s_flexcanInfo.baudrateDetect = true;

        // select default baud rate 1M
        s_flexcanInfo.baudrate = FLEXCAN_MAX_SPEED - 1;
    }
    else
    {
        // baud rate config specified
        s_flexcanInfo.baudrateDetect = false;

        if (canConfig1 & FLEXCAN_SPEED_SPEC_MASK)
        {
            // specified baud rate setting directly
            s_flexcanInfo.baudrate = FLEXCAN_MAX_SPEED;

            // get config data from BCA area
            canConfig2 = g_bootloaderContext.propertyInterface->store->configurationData.canConfig2;

            // prepare specified config data
            bit_rate_table1.pre_divider = (canConfig2 & FLEXCAN_PRESCALER_MASK) >> FLEXCAN_PRESCALER_SHIFT;
            bit_rate_table1.pseg1 = (canConfig2 & FLEXCAN_PSEG1_MASK) >> FLEXCAN_PSEG1_SHIFT;
            bit_rate_table1.pseg2 = (canConfig2 & FLEXCAN_PSEG2_MASK) >> FLEXCAN_PSEG2_SHIFT;
            bit_rate_table1.rjw = canConfig2 & FLEXCAN_RJW_MASK;
            bit_rate_table1.propseg = (canConfig1 & FLEXCAN_PROPSEG_MASK) >> FLEXCAN_PROPSEG_SHIFT;
        }
        else
        {
            // specified speed index, baud rate settings from bootloader
            s_flexcanInfo.baudrate = canConfig1 & FLEXCAN_SPEED_INDEX_MASK;

            if (s_flexcanInfo.baudrate >= FLEXCAN_MAX_SPEED)
            {
                s_flexcanInfo.baudrate = FLEXCAN_MAX_SPEED - 1;
            }
        }
    }

 

 This is how the tool KinetisFlashTool.exe looked like after selecting the parameters I wanted:
KinetisFlashTool-CAN-125KHz.png

1,278 Views
callendorph
Contributor I

Confirmed - this solution works for both 1Mbps and 125kbps.

0 Kudos
1,302 Views
vicentegomez
NXP TechSupport
NXP TechSupport

would be possible that you test it on the freedom board?

Maybe you have a hardware issue,

 

we have more customers using the ROM bootloader with CAN

 

0 Kudos