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.

TMS320F2837xD programming CPU2 flash from RAM

Other Parts Discussed in Thread: TMS320F28377D, CONTROLSUITE

Hi,


I am working with TMS320F28377D and I have developed my own RAM bootloader which can program(using Flash API) the CPU1 flash of this device. the bootloader is loaded to direct to RAM using Boot ROM functions. For this project I'm using the linker command file "2837xD_RAM_lnk_cpu1.cmd". Everything works (erase, program and verify operation) very well.

Now I want program flash of CPU2 but I don't know how can I do that. Is it enough to use the "2837xD_RAM_lnk_cpu2.cmd" linker file and rebuild existing project for CPU1? Will be it works?

Or is it needed to use the other linker command file? Which(in ti\controlSUITE\device_support\F2837xD\v180\F2837xD_common\cmd exist many of cmd files)?


I have also question about FlashBank selection for Flash API functions. Does it mean that "Fapi_FlashBank0" is fo CPU1 flash and Fapi_FlashBank1 is for CPU2 flash? Or Fapi_FlashBank0 is the same for CPU1 and CPU2 flash?

Thank you for your quick responses!

Best regards,

Tomas

[unlocked 11/21/17 LE]

  • Hi Tomas,

    You can use  "2837xD_RAM_lnk_cpu2.cmd" for your CPU2 project.  

    Regarding the Bank0/1 question:  You should use Fapi_FlashBank0 for CPU2 as well since CPU2-Bank is Bank0 for CPU2.  Please check out the CPU2 flash programming example code flash_programming_cpu02.c at C:\ti\controlSUITE\device_support\F2837xD\v190\F2837xD_examples_Dual\flash_programming\cpu02.  This example copies Flash API from Flash to RAM before programming CPU2;  you don't have to do that since you said you are loading everything to RAM.  Best rest of the example should help. 

    Note that for CPU2 flash programming, you need to gain Flash pump semaphore for CPU2.  You can use the function "SeizeFlashPump()" available in F2837xD_SysCtrl.c and it when compiled for CPU2 (CPU2 should be a predefined symbol), will gain the semaphore for CPU2.

    Please make sure to configure the clock from CPU1 before doing Flash operations on CPU2.

    Let me know if you have any questions.

    Thanks and regards,

    Vamsi

  • Hi Vamsi,

    thank you for your reply. I try doing anything with my project but I can't access CPU2 flash. You wrote "Please make sure to configure the clock from CPU1 before doing Flash operations on CPU2".  What did you mean by this?

    I have some mismatch how to configure my CPU1 project for flashing CPU2 flash. I also take a look to mentioned "flash_programming\cpu02" project. When I compare it with "flash_programming\cpu01" project there is a very little changes. Can you please concretely describe steps how to change CPU1 project for programming CPU2 flash?

    I try do following:

    1. In actual CPU1 project(which use F2837xD_Headers_nonBIOS_cpu1.cmd and 2837xD_RAM_lnk_cpu1.cmd, predefined symbol CPU1)  I replace the gain pump semaphore "SeizeFlashPump"with statement to change pump_ownership to CPU2.

    2. Now I try debug this code but I am not able to change pump_ownership to CPU2(Note: I try to debug ControlSuite "flash_programming\cpu02" project but I also cannot change the pump_ownership to CPU2. The while loop repeats to infinite...). Don't you know why?

    Is this procedure above correct? I'm attaching my project for reference. I will be very grateful if you look on it and help me modifying it.

    CPU2_RAM_program.zip

    I have some additional questions:

    1. I suppose that if I have working project for CPU1 then I should be able to port it to CPU2 without any issue. Am I right?

    2. I'm using access to  "GpioCtrlRegs" device registers in my project for CPU1(GPIO pins are used for device synchronization with host). From technical reference manual I see that these registers are available only on CPU1. Does it mean that for working with CPU2(predefined symbol CPU2 in project) I need to rewrite code to GPIO_ReadPin/GPIO_WritePin?

    3.  How the code knows to which flash(CPU1 or CPU2) is going to access? Is this flash selection executed by flash pump ownership? Or is there any other "switch"? Or it cannot be said that only one switch decide which CPU flash will be selected?

    Thanks and regards,

    Tomas

  • Tomas,

    Regarding the clock:  As you know, Flash API should be initialized using Fapi_initializeAPI() function before using Flash API functions to erase/program the flash.  One of the parameters that you pass to this function is the operational frequency (clock that you configured for your application for example 200MHz).  Assuming that you are using CPU1 to configure the PLL, I am suggesting you to make sure that PLL is configured for the required frequency by CPU1 before you execute the Fapi_initializeAPI() function on CPU2.  You can sync between the two cores using IPC.

    Regarding the pump semaphore switching issue:  Did you check whether CPU1 is releasing the semaphore back to 00 state or not before executing CPU2 code to change the semaphore state?  I see that your CPU2 code is writing 00 - but this write will not succeed if CPU1 is holding the semaphore.

    Regarding the question on which Flash bank gets operated:  If you execute the Flash API from CPU1, CPU1's Flash bank gets erased/programmed.  If you execute the Flash API from CPU2, CPU2's Flash bank gets erased/programmed.

    Regarding the question on porting the CPU1 project to CPU2:  I assume you are asking this in terms of Flash API usage.  If yes, yes, you can port it easily for CPU2.  Only thing that you need to keep in mind is that only one core can do Flash erase/program operations at a given time and pump should be gained by a CPU before doing Flash operations on it's bank.

    Regarding the GPIO question: I would suggest you to start a different thread so that it will be easy for others to read and reply/track.

    Thanks and regards,
    Vamsi

  • Hi Vamsi,


    again thank you for your reply. Your answer surely can help but for me it's always more an more complicated...

    I don't understand how it must work. There is a mixing of using CPU1 and CPU2. In "C:\controlSUITE\device_support\F2837xD\v190\F2837xD_examples_Dual\flash_programming" examples exist two folder with name cpu1 and cpu2. Is this two project cooperating between each other? Or it is independent project one for CPU1 and second for CPU2, and CPU2 project don't depend on CPU1 project?

    You said, that PLL clock must be set by CPU1. OK - when I open the mentioned controlSuite cpu2 flash_programming example, there is predefined symbol "CPU2". Is there sets the correct PLL clock by CPU1? I take this question because I'm not able debug this project because I can't switch pump semaphore to 0x10 value and take the control to CPU2. I don't understand why...

    If example project for CPU2 don't work how can I write my own project? I'm using CCSv5.5.0.00077 and XDS510USB debugger. One note - I can debug CPU1 project without any problems.

    There is also many other questions and I can ask you for a thousand times and the result may be, that I will never solve my problem. I think the better and quicker may be modify my attached project(for CPU1) to work as CPU2 project. As you wrote, it can be easily port to CPU2 use and I will see CONCRETELY steps you do for using this project as CPU2...

    Thanks and regards,

    Tomas

  • Tomas,

    (1) I imported your project and noticed that you have CPU1 as the predefined symbols.  I changed it to CPU2 and then it did not get stuck in the PLL lock infinite loop.  As you know, CPU1 only can access the clock configuration registers by default and hence your code is getting stuck in PLL lock loop.

    (2) To simplify the debug and to narrow down to Flash erase/program issue, I commented out all of the GPIO config code in your code and I am successfully able to change the pump semaphore value for CPU2 and then erase the Flash.  I attached the modified C file here and you can try it.  

    (3) Regarding the flash_programming example:  CPU1 and CPU2 are independent projects but even if you run them at the same time, you would not face any issues since pump semaphore gets grabbed by only one core at a time.  However, if you want to run only CPU2 project, you need to make sure you execute the CPU1 project at least until clock is configured (Meaning you have to execute InitSysCtrl() function on CPU1 for CPU2 to be able to do Flash operations).

    4) If you have other questions with respect to Flash programming, please feel free to ask in this thread.  If you have questions regarding other things, please start a new thread.  

    //###########################################################################
    // FILE:   flash_programming_cpu01.c
    // TITLE:  Flash Programming Example for F2837xD.
    //
    //! \addtogroup dual_example_list
    //! <h1> Flash Programming </h1>
    //!
    //! This example demonstrates F021 Flash API usage.
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v180 $
    // $Release Date: Fri Nov  6 16:19:46 CST 2015 $
    // $Copyright: Copyright (C) 2013-2015 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    #include "F28x_Project.h"     // Device Headerfile and Examples Include File
    
    #include <string.h>
    
    //Include Flash API example header file
    #include "flash_programming_c28.h"
    
    //*****************************************************************************
    // FILE Flash API include file
    //*****************************************************************************
    #include "F021_F2837xD_C28x.h"
    
    //Data/Program Buffer used for testing the flash API functions
    #define  WORDS_IN_FLASH_BUFFER    0x100  // Programming data buffer, words
    
    uint16   Buffer[WORDS_IN_FLASH_BUFFER + 1];
    uint32   *Buffer32 = (uint32 *)Buffer;
    
    //*****************************************************************************
    // Prototype of the functions used in this example
    //*****************************************************************************
    void Example_CallFlashAPI(void);
    
    //*****************************************************************************
    // This is an example code demonstrating F021 Flash API usage.
    // This code is in Flash
    //*****************************************************************************
    void main(void)
    {
    // Step 1. Initialize System Control:
    // Enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
        InitSysCtrl();
    
    //  Unlock CSM
    //
    //  If the API functions are going to run in unsecured RAM
    //  then the CSM must be unlocked in order for the flash
    //  API functions to access the flash.
    //  If the flash API functions are executed from secure memory
    //  then this step is not required.
        //DcsmZ1Unlock();
    
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xD_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
       //InitGpio();  // Skipped for this example
    
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
        DINT;
    
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xD_PieCtrl.c file.
        InitPieCtrl();
    
    // Disable CPU interrupts and clear all CPU interrupt flags:
        IER = 0x0000;
        IFR = 0x0000;
    
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in DSP2802x_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
        InitPieVectTable();
    
    // Copy time critical code and Flash setup code to RAM
    // This includes InitFlash(), Flash API functions and any functions that are
    // assigned to ramfuncs section.
    // The  RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
    // symbols are created by the linker. Refer to the device .cmd file.
    
       //memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    
    // Call Flash Initialization to setup flash waitstates
    // This function must reside in RAM
    
        InitFlash();
    
    //  Gain pump semaphore
    //    SeizeFlashPump();
    
        //change pump to read-only state
        EALLOW;
    	while (FlashPumpSemaphoreRegs.PUMPREQUEST.bit.PUMP_OWNERSHIP != 0x0)
    	{
    		FlashPumpSemaphoreRegs.PUMPREQUEST.all = IPC_PUMP_KEY | 0x0;
    	}
    	EDIS;
    
    	//change pump to CPU2
    	EALLOW;
    	while (FlashPumpSemaphoreRegs.PUMPREQUEST.bit.PUMP_OWNERSHIP != 0x1)
    	{
    		FlashPumpSemaphoreRegs.PUMPREQUEST.all = IPC_PUMP_KEY | 0x1;
    	}
    	EDIS;
    
    //  Jump to RAM and call the Flash API functions
        Example_CallFlashAPI();
    }
    
    void Synchronize_with_host(void)
    {
    	Uint32 variable;
    	Uint16 i;
    /*
    		//synchronization from device, indicates L
    		EALLOW;
    		    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0;	//GPIO
    		   	GpioCtrlRegs.GPADIR.bit.GPIO19 = GpioCtrlRegs.GPADIR.bit.GPIO19 | (1);	//output
    		   	GpioDataRegs.GPADAT.bit.GPIO19 = 0;	//pin GPIO19 to L
    		EDIS;
    
    		for (i = 0; i < 2; i++)
    		{
    	   	//synchronization from host, wait to H
    	   	do
    	    {
    	    EALLOW;
    	    	GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 0x0000;
    	        GpioCtrlRegs.GPADIR.bit.GPIO18 = GpioCtrlRegs.GPADIR.bit.GPIO18 | (0); //input
    	        variable = GpioDataRegs.GPADAT.bit.GPIO18;
    	    EDIS;
    	    }
    	   	while((variable & 0x0001) != 0x0001);
    
    		// synchronization from device, indicates H
    		EALLOW;
    			GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0x0000;
    		    GpioCtrlRegs.GPADIR.bit.GPIO19 = GpioCtrlRegs.GPADIR.bit.GPIO19 | (1);
    		    GpioDataRegs.GPADAT.bit.GPIO19 = 1;	//pin GPIO19 to H
    		EDIS;
    
    	   	// synchronization from host, wait to L
    	   	do
    	    {
    	    EALLOW;
    	    	GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 0x0000;
    	      	GpioCtrlRegs.GPADIR.bit.GPIO18 = GpioCtrlRegs.GPADIR.bit.GPIO18 | (0);
    	      	variable = GpioDataRegs.GPADAT.bit.GPIO18;
    	    EDIS;
    	    } while((variable & 0x0001) == 0x0001);
    
    	   	//synchronization from device, indicates L
    	   	EALLOW;
    	        GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0x0000;
    	      	GpioCtrlRegs.GPADIR.bit.GPIO19 = GpioCtrlRegs.GPADIR.bit.GPIO19 | (1);
    	      	GpioDataRegs.GPADAT.bit.GPIO19 = 0;	//pin GPIO19 to L
    	    EDIS;
    		}
    		*/
    }
    
    
    //*****************************************************************************
    //  Example_CallFlashAPI
    //
    //  This function will interface to the flash API.
    //  Flash API functions used in this function are executed from RAM
    //*****************************************************************************
    #pragma CODE_SECTION(Example_CallFlashAPI, "ramfuncs");
    void Example_CallFlashAPI(void)
    {
    
    	Fapi_StatusType            oReturnCheck;
        volatile Fapi_FlashStatusType       oFlashStatus;
        Fapi_FlashStatusWordType   oFlashStatusWord;
    
        //Najprv musim odstartovat algo
        Synchronize_with_host();
    
        // Disable ECC.  ECC does not have to be disabled to do FSM operations like
        // program and erase.
        // However, on Sonata Rev. 0 silicon, due to an OTP ECC errata,
        // disable ECC to avoid ECC errors while using Flash API functions that
        // read TI-OTP
        EALLOW;
        Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0x0;
        EDIS;
    
        // This function is required to initialize the Flash API based on System
        // frequency before any other Flash API operation can be performed
        EALLOW;
    	oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 200);//for now keeping it out
    	EDIS;
        if(oReturnCheck != Fapi_Status_Success)
        {
            // Check Flash API documentation for possible errors
        }
    
        // Fapi_setActiveFlashBank function sets the Flash bank and FMC for further
        // Flash operations to be performed on the bank
        EALLOW;
        oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
        EDIS;
        if(oReturnCheck != Fapi_Status_Success)
        {
            // Check Flash API documentation for possible errors
    
        }
    
        EALLOW;
        // Erase the sectors that we have programmed above
        // Erase Sector C
        oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,
                       (uint32 *)Bzero_SectorA_start);
    
        // Wait until FSM is done with erase sector operation
        while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
    
        // Verify that SectorC is erased.  The Erase step itself does a verify as
        // it goes.
        // This verify is a 2nd verification that can be done.
        oReturnCheck = Fapi_doBlankCheck((uint32 *)Bzero_SectorA_start,
                       Bzero_16KSector_u32length,
                       &oFlashStatusWord);
        EDIS;
    
    
        EALLOW;
        // Enable ECC
        Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;
        EDIS;
    
        // Leave control over flash pump
        ReleaseFlashPump();
    
    }	//Example_CallFlashAPI(void)
    
    

    Thanks and regards,
    Vamsi

  • Hi Vamsi,

    I think, I'm beginning to understand how it must work. The difference between your debugging and my was, that you also run the code for CPU1 and configure the clock. I didn't do it...

    OK...so now the other question has become a high priority. i explain :

    1. I have a project only for CPU1, where for CPU2 programming purposes will be the clock configuration. I can build this project and generate *.hex file(from *.out file) and load this hex data direct to RAM(via BootROM function) and run it - this is no problem.

    2. I have the second project only for CPU2 where for example will be blinking application(or erase flash API, it doesn't matter for this time). I build this project and generate the *.hex file.

    3. Now I have a problem - how can I load this hex file(for CPU2) to CPU2 RAM? Direct access using BootROM is not possible because I can't access via GPIOs CPU2 RAM location. In addition I have read in spruhm8e(technical reference manual), page 528 that :

    "CPU1 acts as master system in the device
    controlling the overall boot process on CPU2 system. If booting from one of the bootable peripherals then
    CPU1 Boot ROM gets the application code to be run on CPU1 and loads into device RAMs (M0, M1,LS0-
    LS5, D0, D1, and GS0-GS15 shared RAM) and starts the CPU1 application. It is the responsibility of
    CPU1 user application to either move the code from CPU1 RAMs to CPU2 RAM(s)"

    Is there any example where I can find the code moving from CPU1 RAM to CPU2 RAM and run it in CPU2?

    Thanks,

    Tomas

  • Tomas,

    Check out the USB flash kernel example in Controlsuite at C:\ti\controlSUITE\device_support\F2837xD\v190\F2837xD_examples_Dual\F2837xD_usb_flash_kernels.

    Check out the comments in the F2837xD_usb_flash_kernels_cpu01.c file.  In this example, CPU2 Flash kernel and CPU2 Flash image are loaded in to shared RAM by CPU1 and CPU2 executes from shared RAM to program it's Flash.  If not USB, you can use any other bootmode if you want.  Let us know if you have any questions.

    Thanks and regards,
    Vamsi

  • Hi Vamsi,

    thank you for your support! I'm able to copy blinky CPU2 project to the shared GSx RAM using CPU1, and execute this code by CPU2. The positive is that LED is blinking as I expect :-) Great! Now I need to develop the functional bootloader for CPU2. I assume that loading of bootloader to the shared RAM is now solved and will be work also for Flash API.

    Again thank you for your help!
    Best regards,
    Tomas