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.

CC2540 Flash write issue

Hello,

I'm trying to write to the flash in order to implement a bootloader. I have been trying with my own code and with the hal code, but I can't see any change in the flash. I have included my code.

The debug variable fctl remains at 0x04 in all cases. Running the hal produces the same result - FCTL never changes from 0x04. So it seems that I never get FULL, BUSY or ABORTED. Any ideas on why this piece of code doesn't work? I'm running CCDebugger in IAR.

	IEN0 &= ~0x80;
		
	FADDRH = 0x02;
	FADDRL = 0x00;
	
	FCTL |= 1<<1;
	for(int i=0;i<size;i++)
	{
		FWDATA = buffer[i];
		fctl	= FCTL;
		while(FCTL & 0xC0);
	}

	IEN0 |= 0x80;

  • Hi Johan,

    You should use the DMA for Flash writes. The Flash Write word is 32 bits so the FWDATA register needs to be written 4 times for each write operation. It then gets tricky if you run the code out of Flash, because it will be stalled for reads during the Flash operation.

    The other alternative is to run the flash writes out of RAM.

    There is example code in the user guide.

    Peder

  • Easiest is to use HalFlashWrite(), in hal_flash.c

  • I tried the hal function too, but it had the same result. The flash data doesn't change and FCTL never reads anything else than 0x04, which is the reset value. For example I would call it like this: HalFlashWrite(0xC000/4, buffer, size/4); After the write I would watch (char*)0xC000 and see only FFs. I can see in the HalFlashWrite function that it never waits for completion in the busy-loop, so the busy flag is never active.

    Is it not the case that the flash read only gets stalled after writing 4 bytes to FWDATA, when there is an actual write going on? Or is it stalled directly when FCTL.WRITE is 1?

  • Not sure how you're "watching" memory, but flash memory addresses do not map directly to CPU memory addresses.  The 254x has 128kb or 256kb of flash, but the CPU has only 64kb of address space.  It is likely that the write succeeds, but you're looking for data in the wrong place. The 254x User Guide section 2.2 has a good description of memory mapping.

  • It was indeed only a matter of memory mapping - I was supplying the memory mapped address to HalFlashWrite instead of the correct flash address.

  • Could you explaid how did you solve it?
    I've spend many days trying to solve de exactly same problem.
    Thanks.
    Alfred.
  • Hello,

    this is how my code is looking now in the bootloader, where I'm using the hal driver. I believe I call it with addresses from 0x00000000 and up

    flash.c

    #include "Main.hpp"
    
    #define FLASH_PAGE_SIZE		2048
    #define FLASH_WORD_SIZE		4
    
    // Write an arbitrarily sized block to the address supplied
    void Flash_Write(unsigned long address, unsigned char *buffer, unsigned int size)
    {
      	long endAddress = address+size;
    	unsigned int writeSize = 0;
    	
      	for(int i=0; i<size; i+=writeSize)
    	{
    	  	long writeAddress = address + i;
    	  	if(!(address % FLASH_PAGE_SIZE))
    		{	
    	  		int page 	= address / FLASH_PAGE_SIZE;
    		  	HalFlashErase(page);
    		}
    		int max = 2048 - (writeAddress % 2048);
    	  	writeSize = endAddress - writeAddress;
    		if(writeSize > max)
    		  	writeSize = max;
      		P0_5 = 1; // write time debug
    		HalFlashWrite(writeAddress/4, buffer+i, writeSize/4);	
    		P0_5 = 0;
    	}
    }
    
    // Read an arbitrarily sized block from the address supplied, and return the sum
    unsigned char Flash_Read(unsigned long address, unsigned char *buffer, unsigned int size)
    {  	
      	int page 	= address / FLASH_PAGE_SIZE;
      	int offset 	= address % FLASH_PAGE_SIZE;
    	HalFlashRead(page, offset, buffer, size);	
    	
      	unsigned char sum = 0;
      	while(size--)
    		sum += buffer[size];
    
    	return sum;
    }

    In the firmware I'm using the hal functions a bit like this:

    volatile __code const uint8 someBackup[4] = {0xFF,0xFF,0xFF,0xFF};

    HalFlashWrite((uint16)someBackup>>2, (unsigned char*)&dataToBackup, 1);

  • NV storage using page/offset addressing

    // write 32-bit word to flash
    // page - flash page (0-127)
    // offset - offset into the page (0-2047)
    // pBuf - source buffer.

    void myFlash_writeWord( uint8 page, uint16 offset, uint32 *pWord )
    {
    uint16 flashAddr;

    // offset must be on 4-byte boundary
    MY_ASSERT (0 == (offset & 0x3));

    // address passed to HalFlashWrite is actual address in flash / 4, i.e. word address
    // actual address is (page * 2048) + offset
    // dividing actual address by 4 results in (page * 512) + offset/4
    flashAddr = (offset >> 2) + ((uint16)page << 9);

    // write it out
    HalFlashWrite(flashAddr, (uint8*)pWord, 1);
    }