This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: Using DCSM protection inside bootloader application

Part Number: TMS320F28379D

Hello!

We have developed a solution that includes a bootloader and application for the F28379D device. Now we want to protect the flash memory readings, so we have activated the Zone 1 protection to all memories (FLASH and RAM) for both CPUs.

The problem we have now is on the bootloader. We are not able to enable the bootloader on CPU2. I will explain briefly the boot sequence:

  1. CPU1 starts running
  2. Through serial commands, the CPU 1 is erased and flashed
  3. CPU1 gives control of peripherals to CPU2 and then runs it through IPC commands and waits to CPU2
  4. CPU2 starts running, erasing and flashing its own memory
  5. When CPU2 finishes, notify to CPU1
  6. CPU1 resets both CPUs

This was working perfectly until we lock the memories.

Now we are able to flash CPU1 successfully (we have included the unlock sequence inside code) but when CPU1 runs CPU2, it looks like that this one is not started properly. We don't have too much information because we cannot debug the CPUs if they are protected. We, we can debug CPU1, but not CPU2.

Is it the DCSM affecting to the IPC peripheral? Is there any specific boot sequence for CPU2 if the protections are enabled?

Thank you

  • IPC should not be causing this issue. I am suspecting that unlock sequence on CPU2 is not working properly. Can you confirm you are running unlock sequence on CPU2 as well?

    Regards,

    Vivek Singh
  • I can't confirm if it is working or not. If I debug de CPU2, I must to unlock it before debugging, so the result of the unlocking sequence is always OK. This is the first function I call in the main for both CPUs:

        uint16_t u16Err = BOARD_OK;
        uint32_t u32Password0, u32Password1, u32Password2, u32Password3;
    
        EALLOW;
    
        /* TI recommended dummy read sequence */
        u32Password0 = DcsmZ1Regs.Z1_CSMKEY0;
        u32Password1 = DcsmZ1Regs.Z1_CSMKEY1;
        u32Password2 = DcsmZ1Regs.Z1_CSMKEY2;
        u32Password3 = DcsmZ1Regs.Z1_CSMKEY3;
    
        /*
         * Forcing to use password variables to
         * avoid compilation warning
         */
        u32Password0 = p32Data[0];
        u32Password1 = p32Data[1];
        u32Password2 = p32Data[2];
        u32Password3 = p32Data[3];
    
        /* Unlock the device */
        DcsmZ1Regs.Z1_CSMKEY0 = u32Password0;
        DcsmZ1Regs.Z1_CSMKEY1 = u32Password1;
        DcsmZ1Regs.Z1_CSMKEY2 = u32Password2;
        DcsmZ1Regs.Z1_CSMKEY3 = u32Password3;
        EDIS;
    
        /* Check lock status */
        if (DcsmZ1Regs.Z1_CR.bit.UNSECURE == 0)
        {
            u16Err = BOARD_LOCKED;
        }
        return u16Err;

    I'm pointing to IPC because in the CPU2 boot sequence where the IPCBOOTMODE is chosen, the ti example code set the IPC flags to 0x80000001. I have modified this flag to indicate to CPU2 if it must load the bootloader or the application for example:

    • 0x83333331 runs bootloader
    • 0x80000001 runs application

    Before locking the memories, this was working perfectly. I suspect that the problem could be that the CPU2 is always trying to run the application (now an empty one).

    What I see is once the cpu2 must take control of the bootloader, the communications are KO. 

    The other option I have in mind is the mapping of the peripherals. Could they be affected by the memory protection?

  • Is there any suggestion about this topic?

  • Hi,

    The other option I have in mind is the mapping of the peripherals. Could they be affected by the memory protection?

    No that is not impacted by memory protection.

    Have you tested the same code before enabling the security and did it work fine?

    Regards

    Vivek Singh

  • Hi,

    Vivek Singh said:
    Have you tested the same code before enabling the security and did it work fine?

    Yes, it works fine without protection. With protection only works CPU1. So I'm doing something wrong during transition between CPU1 and CPU2. Both CPU executes exactly the same unlocking sequence.

    Both CPUs are locked with the same password and zone

  • I read your code again and one observation -

    In below code you are reading the CSMKEYx register where as you are suppose to dummy read the password location address in USER OTP not register. Can you change that and see this helps.

    /* TI recommended dummy read sequence */

    u32Password0 = DcsmZ1Regs.Z1_CSMKEY0;

    u32Password1 = DcsmZ1Regs.Z1_CSMKEY1;

    u32Password2 = DcsmZ1Regs.Z1_CSMKEY2;

    u32Password3 = DcsmZ1Regs.Z1_CSMKEY3;

    Regards,

    Vivek Singh
  • Thank you for your reply.

    I have modified the code to this one:

    uint16_t u16Idx;
    long int temp;
    volatile long int *CSMPWL = (volatile long int *)0x78028;

    /* TI recommended dummy read sequence */
    for (u16Idx = 0; u16Idx < 4; u16Idx++)
    {
    temp = *CSMPWL++;
    }

    EALLOW;

    /* Unlock the device */
    DcsmZ1Regs.Z1_CSMKEY0 = u32Password0;
    DcsmZ1Regs.Z1_CSMKEY1 = u32Password1;
    DcsmZ1Regs.Z1_CSMKEY2 = u32Password2;
    DcsmZ1Regs.Z1_CSMKEY3 = u32Password3;
    EDIS;

    But it is still not working,

    What I cannot understand is why it is working for CPU1 but not for CPU2. It is exactly the same code.
  • On CPU2, if you write the KEY value from CCS memory watch window (or register view), does it get unlock?

    Vivek Singh
  • Did you check if you are able to unlock the CPU2 by entering the KEYs manually into CCS register view?

  • Yes, I have the same behaviour.

    I did this:

    • I set up the debugging session to connect to the MCU without loading a program
    • I connect the debug session to both CPUs
    • I have opened the registers view and I have written the password on both CPUs
    • Run both CPUs
    • Execute the bootloader tool

    CPU1 has been written but CPU2 is locked. I'm not sure if this test is valid because usually when I connect to both CPUs to the debugger, I have an initialisation function that checks the status of the CPUs:

            case CPU_1:
                /* If CPU2 has already booted, return a fail to let the application
                 * know that something is out of the ordinary. */
                if ((IpcRegs.IPCBOOTSTS & (uint32_t)0xF) == C2_BOOTROM_BOOTSTS_C2TOC1_BOOT_CMD_ACK)
                {
                    u16Ret = 1;
                }
    
                if (u16Ret == 0)
                {
                    /* Wait until CPU02 control system boot ROM is ready to receive
                     * CPU01 to CPU02 INT1 interrupts. */
                    while ((IpcRegs.IPCBOOTSTS & C2_BOOTROM_BOOTSTS_SYSTEM_READY ) != C2_BOOTROM_BOOTSTS_SYSTEM_READY )
                    {
                    }
    
                    while ((IpcRegs.IPCFLG.bit.IPC0 == (uint16_t)1) ||
                           (IpcRegs.IPCFLG.bit.IPC31 == (uint16_t)1))
                    {
                    }
    
                    /** Boot up CPU2 from FLASH */
                    IpcRegs.IPCBOOTMODE = (uint32_t)0xB;
    
                    /* CPU01 To CPU02 IPC Command Register */
                    IpcRegs.IPCSENDCOM = BROM_IPC_EXECUTE_BOOTMODE_CMD;
    
                    /* CPU01 to CPU02 IPC flag register */
                    IpcRegs.IPCSET.all = (uint32_t)0x8F0F0F01UL;
    
                }
                break;
            case CPU_2:
                IpcRegs.IPCSET.all = (uint32_t)0x55555555UL;
                break;

    Usually the first check gives an error because CPU2 is booted up from the debugger so it is already running. To over come that, when the CPUs are not locked, before running the application I reset boths CPUs and then run the application, then is CPU1 who wakes up CPU2. The problem when CPUs are locked is that I cannot reset the CPUs before running because I loose the access to the memory.

  • When you write the password values to CPU2 via register view, do you get access to memories? You don't need to run the code to check this. Just write the password via memory watch window and then see if device is un-secure. You can check that by reading the CR register bit of CPU2 or viewing the secure memory content in memory watch window (if it's visible then CPU2 is unsecure).
  • Yes, I'm able to read Flash from both CPUs and I saw I can debug CPU1 even if the flash is locked. So the password on CPU2 via register view is working. I also saw the bit unsecure to 1 after writing the password.

    I have tried to debug the bootloader. I was connected to both CPUs, CPU2 is in reset until CPU1 wakes it up. When CPUs reaches the IPC instructions to wake up CPU2, this is what I see:

  • Hi, sorry for late reply. Code you are running on CPU2 to unlock the CPU2 security is running from secure memory or un-secure memory. It has taken long time to debug this so I would suggest if you could send me the sample code to try this on my setup here to reproduce this issue.

    Regards,
    Vivek Singh
  • Hello

    The code is executed from secure memory if I'm not wrong. Both CPUs have the same secure flash sections and RAM memory in the same secure zone.

    I cannot share our code completely, but there is attached a non-functional  project. It builds but it probably do nothing because the serial protocol is removed. However you can hard-code the SerialBootProcess function to force any of the 4 cases I left which are the main functions accessing to the flash.boot_test.zip