Hello.
Here is the code you requested. This was copied from the Wixel’s bootloader and hopefully it will be useful to you. You do not need to worry about erasing the bootloader on your Wixel because we have enabled write protection on the sections of flash that it occupies.
Global variables you’ll need:
// writeBuffer holds the data from the computer that we want to write in to flash.
XDATA uint8 writeBuffer[1024*3];
// flashWriteDmaConfig holds the configuration of DMA channel 0, which we use to
// transfer the data from writeBuffer in to flash.
XDATA DMA_CONFIG flashWriteDmaConfig;
// startFlashWrite is a small piece of code we store in RAM which initiates the flash write.
// According to datasheet section 12.3.2.1, this code needs to be 2-aligned if it is executed
// from flash. SDCC does not have a good way of 2-aligning code, so we choose to put the code in
// RAM instead of flash.
XDATA uint8 startFlashWrite[] = {
0x75, 0xAE, 0x02, // mov _FCTL, #2 : Sets FCTRL.WRITE bit to 1, initiating a write to flash.
0x22 // ret : Returns to the calling function.
};
One-time setup:
// Configure the flash write timer. See section 12.3.5 of the datasheet.
FWT = 32;
// Set up the DMA configuration block we use for writing to flash (See Figure 21 of the datasheet).
// LENL and LENH are sent later when we know how much data to write.
flashWriteDmaConfig.SRCADDRH = (unsigned short)&writeBuffer >> 8;
flashWriteDmaConfig.SRCADDRL = (unsigned char)&writeBuffer;
flashWriteDmaConfig.DESTADDRH = XDATA_SFR_ADDRESS(FWDATA) >> 8;
flashWriteDmaConfig.DESTADDRL = XDATA_SFR_ADDRESS(FWDATA);
// WORDSIZE = 0 : byte
// TMODE = 0 : single mode
// TRIG = 0d18 : flash
flashWriteDmaConfig.DC6 = 18;
// SRCINC = 01 : yes
// DESTINC = 00 : no
// IRQMASK = 0 : no *datasheet said this bit should be 1
// M8 = 0 : 8-bit transfer
// PRIORITY = 0b10 : high
flashWriteDmaConfig.DC7 = 0b01000010;
DMA0CFG = (uint16)&flashWriteDmaConfig;
Erasing a page of flash:
// To erase a page, set FADDRH and then call this function.
void eraseFlashPage()
{
FCTL = 1; // Set FCTL.ERASE to 1 to initiate the erasing.
__asm nop __endasm; // Datasheet says a NOP is necessary after the instruction that initiates the erase.
__asm nop __endasm; // We have extra NOPs to be safe.
__asm nop __endasm;
__asm nop __endasm;
while(FCTL & 0x80){}; // Wait for erasing to be complete.
}
Writing to flash:
FADDR = address >> 1;
flashWriteDmaConfig.VLEN_LENH = length >> 8;
flashWriteDmaConfig.LENL = length;
DMAIRQ &= ~(1<<0); // Clear DMAIF0 so we can poll it to see when the transfer finishes.
DMAARM |= (1<<0);
__asm lcall _startFlashWrite __endasm;
while(!(DMAIRQ & (1<<0))){} // wait for the transfer to finish by polling DMAIF0
while(FCTL & 0xC0){} // wait for last word to finish writing by polling BUSY and SWBUSY
–David