I have a board with a CC2543, running 32MHz. Compiler is IAR. I am using the TI CC2543 development kit with a debug cable between it at the board. Everything works perfectly: download code, single stepping, setting breakpoints, examining registers, memory, etc.
I am attempting to write four bytes to flash memory at 0xFC00. The code was taken from some demo code I found on the TI development site. It works perfectly when I run the program from the debugger, i.e., download the code and start the program. Now here is where is gets really strange. All I do is next is remove the debug cable and cycle power to the board. The program runs perfectly but fails to write the flash. It remains unchanged.
The "write_flash()" function is listed below. It uses DMA to write a four-byte array 'finalCardCount' to flash at 0xFC00.
To examine what was going on, I used an unused port, P1_1, to toggle a signal that I could examine on a o'scope. That proved the program is definitely running the function. Then I added other port toggles around various sections of the code, running it with the debugger attached and stand-alone. That allowed me to see that it was actually exercising all the code, and also record how long it was taking to run various statement.
There were two huge differences when running with the debugger vs. stand-alone.
1. The statement "FCTL |= FCTL_ERASE;" takes 904nS to execute when running stand-alone, but 21.6mS when attached to the debugger.
2. The statement "FCTL |= FCTL_WRITE;" takes 1.16uS to execute when running stand-alone vs. 44.8uS.
All the other parts of the code run the same in both debug and stand-alone mode.
The datasheet says that a page erase (the first statement) should take ~20mS and a four-byte write (the second statement) should take ~20uS, which are in the right neighborhood for the values I measured when running with the debugger. The values when running stand-alone are much too short.
I'm at a loss to explain this. What is going on when the debugger is running vs. stand-alone? As proven by observing the port-toggles, the program is definitely executing the two "FCTL |= " statements. Does debug mode somehow permit erasures and writes but when the program just run normally, that access is denied? The fact that the statements return so quickly without performing the write tells me something is cancelling the erase or write.
=======================
void write_flash(void)
{
P1_1 = 1; //set port so we can tell function is running on 'scope
DMA_DESC dmaConfig0;
dmaConfig0.SRCADDRH = ((uint16)finalCardCount >> 8) & 0x00FF;
dmaConfig0.SRCADDRL = (uint16)finalCardCount & 0x00FF;
dmaConfig0.DESTADDRH = ((uint16)&FWDATA >> 8) & 0x00FF;
dmaConfig0.DESTADDRL = (uint16)&FWDATA & 0x00FF;
dmaConfig0.VLEN = DMA_VLEN_USE_LEN;
dmaConfig0.LENH = (FINAL_CARD_COUNT_ARRAY_SIZE >> 8) & 0x00FF;
dmaConfig0.LENL = FINAL_CARD_COUNT_ARRAY_SIZE & 0x00FF;
dmaConfig0.WORDSIZE = DMA_WORDSIZE_BYTE;
dmaConfig0.TMODE = DMA_TMODE_SINGLE;
dmaConfig0.TRIG = DMA_TRIG_FLASH;
dmaConfig0.SRCINC = DMA_SRCINC_1;
dmaConfig0.DESTINC = DMA_DESTINC_0;
dmaConfig0.IRQMASK = DMA_IRQMASK_ENABLE;
dmaConfig0.M8 = DMA_M8_USE_8_BITS;
dmaConfig0.PRIORITY = DMA_PRI_HIGH;
/* The DMA configuration data structure may reside at any location in
* unified memory space, and the address location is passed to the DMA
* through DMA0CFGH:DMA0CFGL.
*/
DMA0CFGH = ((uint16)&dmaConfig0 >> 8) & 0x00FF;
DMA0CFGL = (uint16)&dmaConfig0 & 0x00FF;
// Waiting for the flash controller to be ready.
while (FCTL & FCTL_BUSY);
/* Configuring the flash controller.
* FADDRH:FADDRL: point to the area in flash to write to.
*/
uint16 addr;
addr = (uint16)flashDataAddr >> 2; // You address 32-bit words through the flash controller.
FADDRH = (addr >> 8) & 0x00FF;
FADDRL = addr & 0x00FF;
// Erase the page that will be written to.
FCTL |= FCTL_ERASE;
// Wait for the erase operation to complete.
while (FCTL & FCTL_BUSY);
// Arm the DMA channel, takes 9 system clock cycles.
DMAARM |= DMAARM_DMAARM0;
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP(); // 9 NOPs
// Enable flash write. Generates a DMA trigger.
FCTL |= FCTL_WRITE;
// Wait for DMA transfer to complete.
while (!(DMAIRQ & DMAIRQ_DMAIF0));
// Wait until flash controller not busy.
while (FCTL & (FCTL_BUSY | FCTL_FULL));
/* By now, the transfer is completed, so the transfer count is reached.
* The DMA channel 0 interrupt flag is then set, so we clear it here.
*/
DMAIRQ = ~DMAIRQ_DMAIF0; // Clear interrupt flag by R/W0, see datasheet.
P1_1 = 0; //clear port indicating function exit
}