Hello,
are there any code examples available how to use the F021 Flash API in Concerto ?
I'm especially interested how to properly link the F021_API_CortexM3_LE.lib so that it can be copied to SRAM for executionand how to set/get the the correct load (SRAM) and store (Flash) addresses.
Thank you in advance,Mario
Mario:
Currently, there is not yet a code example for the F021 Flash API in Concerto. The plan is to release a basic example by the next release of controlSUITE though.
Regards, Chrissy Chang
If a post answers your question, please mark it with the "verify answer" button.
Chrissy,
thank you for your fast answer. When do you expect the next ControlSuite release ? Is there any chance to get some preliminary code/hints etc. ?
Best regards,Mario
Hi Mario,
You ask an extremely good question. The short answer is no, there aren't any examples that have been released yet. However, I'm working on a Flash bootloader for Concerto, so I should be able to help you out directly.
With previous C2000 flash APIs, the library code was assigned to a section called ramfuncs. This made it easy for customers to use a generic linker command file and simply call the memcopy function before calling the flash functions. The F021 (Concerto) API is done slightly differently in that it is not part of any pre-defined section. The user must manually link this library into a section that will be copied into RAM. This can easily be done using the linker command file...see below for an example:
GROUP { ramfuncs { -l F021_API_CortexM3_LE.lib} } LOAD = FLASHLOAD, RUN = C0, LOAD_START(RamfuncsLoadStart), LOAD_SIZE(RamfuncsLoadSize), RUN_START(RamfuncsRunStart), PAGE = 0
More information about linking in libraries can be found in the assembly language tools user guide for the ARM compiler (spnu118j). Beyond that all you will need to do is extern the Load/Run symbols in your main.c:
#include <string.h>#include "F021_Concerto_Cortex.h"extern unsigned int RamfuncsLoadStart;extern unsigned int RamfuncsLoadSize;extern unsigned int RamfuncsRunStart;
and then call memcpy before initialize the Flash API:
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize); oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 80);
Please note we have deprecated the old MemCopy function that used to be found in utils/memcopy.c. Instead we are now using the C standard memcpy which is part of the runtime support library.
Hope this helps, let me know if you have further questions,
Trey German
C2000 Applications
Mario,
I put together some example code that is working. Here are a few more pointers:
// Give M3 Control of the flash pump HWREG(MTOCIPC_BASE + IPC_O_MPUMPREQUEST) = IPC_MPUMPREQUEST_KEY | 0x2;
The IPC_MPUMPREQUEST_KEY isn't defined in the current device support release, but you can add:
#define IPC_MPUMPREQUEST_KEY 0xA5937EC0 // Key Value
to the top of you main source file.
// Setup main clock tree for 75MHz - M3 and 150MHz - C28x SysCtlClockConfigSet(SYSCTL_SYSDIV_1 | SYSCTL_M3SSDIV_2 | SYSCTL_USE_PLL | (SYSCTL_SPLLIMULT_M & 0x0F));
before calling anything from the Flash API.
#pragma CODE_SECTION(flashTest, "ramfuncs");void flashTest(void){ unsigned char pucProgTest[0x100]; unsigned int i; Fapi_StatusType oReturnCheck; Fapi_FlashStatusType oFlashStatus; Fapi_FlashBankSectorsType oMyBank; Fapi_FlashStatusWordType oBlankStatus; for(i=0 ; i<0x100; i++) pucProgTest[i] = i; oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 75); oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0); oReturnCheck = Fapi_getBankSectors(Fapi_FlashBank0, &oMyBank); oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, 2); while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy) { } oFlashStatus = Fapi_getFsmStatus(); oReturnCheck = Fapi_doBlankCheck(0x208000, 0x1000, &oBlankStatus); for(i=0 ; i<0x10; i++) { oReturnCheck = Fapi_issueProgrammingCommand(0x208000 + (i*0x10), pucProgTest + (i*0x10), 0x10, 0, 0, Fapi_AutoEccGeneration); while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy) { } oFlashStatus = Fapi_getFsmStatus(); } while(1); }
Let me know if you have any trouble,
Hi,
I follow your example and it's a real pleasure to make it work.
But now, I try to do the same on the C28 side but I can't found some information about the C28's IPC PUMP REQUEST.
So I was wondering if you could provided me some lines. I already got the Flash API example, I just need to give C28 the control of the flash pump.
thank you for your help.
Hello Jeremy,
I would suggest to try the below code.
EALLOW; // Wait for flashpump to be idle while(CtoMIpcRegs.CPUMPREQUEST != 0){} // Take control of the flash pump CtoMIpcRegs.CPUMPREQUEST = 0x4CE73950 | 0x1; EDIS;
Cheers,
Agnès
Agnès Cassin-Delaurière
Thanks
you are always a great help !
Cheers.
Jeremy,
Glad to hear you got it working. Were you able to successfully program flash on the C28x? One some of the parts there is a bug in the ECC patterns that will cause an NMI when flash on the 28 is programmed. Curious if you are seeing this behavior or not.
Regards,
Trey
Hello !
There are a pair of questions about using Fapi.
Q1: When I try to use m3 at frequency 100 (PLL programmed as in lwip example), then function Fapi_setActiveFlashBank returns error Fapi_Error_InvalidHclkValue.
oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 100); oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0); - returns error
But at 75 MHz (PLL programmed as in Fapi example) this couple of functions works fine
oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 75); oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0); - returns success
What's wrong about using Fapi at 100 MHz?
Q2a: I need to program flash with Fapi within both m3 and c28 cores. Both cores' programs executed from Flash and permanently have data in Flash. Ram functions are used only when Fapi job occurs. So what should I do to correctly give "Flash Pump semaphore control" to specified core? Is it up to software to ensure that other core has finished Fapi job before switching semaphore?
Q2b: What should I do when Fapi job is finished if I want to continue executing without restart? Should I "unlock back" semaphore at any core?
As a bonus - there is an error in your example: function oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, 2) isn't workable, there must be 0x208000 instead of "2".
Thanks in advance.
Slava,
A1) Hmmm, I just tried the same thing in my example (which also works at 75Mhz), but I'm having the same issue as you. I believe you should be able to perform flash programming and erase operations at 100Mhz, but I will have to check with our flash experts.
A2a) You are correct, software must ensure the flash pump semaphore is owned by the core doing the flash operations. This should be relatively straightforward as each core can read the state of the semaphore. In software you should just wait to run your programming code until you have the semaphore.
A2b) The semaphore is only needed for programming and erase operations. Normal program reads do not need the semaphore. I would recommend after each core is finished programming you set the semaphore back to its default state.
I'll get back to you on the 100Mhz issue ASAP.
Regards,Trey
Hi all,
Thanks for these posts and the new F021 Flash API example on the concerto.
I still have one question that remains unanswered though:
Does this API and flash technology support re-programming of bits holding zeroes within a previously programmed word?
(This is explicitly stated for other flash APIs but not for the F021. For example on page 5 of the doc for TMS320F2802x Flash API V2.01, it says: ".... a flash or OTP location can be programmed with 0xFFFE and later the same location can be programmed with 0xFFFC without going through an erase cycle. During the second programming call, the program operation will detect that bit 0 was already programmed and will only program bit 1." )
Best regards,
Christian
Christian,
I'm honestly not sure as I haven't given this a shot. I don't see why this wouldn't work, so why don't you give it a shot and let us know if this works or not. I would do it myself, but I'm out on vacation the rest of this week and I'm working on finishing up some other tasks before I go.
In F021 also, a partially programmed word can be programmed to again to change 1s to 0s in later program iterations.
That will work if you don't program ECC. Once you program ECC also for a flash location, you will not be able to reprogram that location to change 1s to 0s with out erase.
Thanks and regards,
Vamsi
For (A1), Before performing FSM operations, you need to set the waitstates for FSM operations calculated using
RWAIT = (SYSCLK/(2*24MHz))-1
If RWAIT results in a fractional value, round it up to the nearest integer. These details are mentioned in the Flash API example. For 100MHz, you have to set RWAIT to 2. For 75MHz, you have to set RWAIT to 1.
Please note that RWAIT for read operation should be calculated differently. See section 5.3 Flash Controller Memory Module and 5.4 Flash registers in Concerto TRM located at http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=spruh22b&fileType=pdf for more details.
Thanks and best regards,
Vamsi,
Thanks for clarifying (I was worried it could effect tear and wear although it works, since you expose the same transistors for more than one programming operation within an erase cycle)
I assume you could also reprogram when the associated ECC byte has been set, provided the reprogramming only ever changes the 8 byte-data block to one that has the same ECC? If this is possible, my next question is how to characterize all 8 byte words having the same 1 byte ECC for a given flash address?