static void flashEraseCallback(void) { // Disable global interrupts IntMasterDisable(); // Erase Flash CCA page FlashMainPageErase(CC2538_FLASH_CCA_ADDRESS); // Reset the board SysCtrlReset(); }
//***************************************************************************** // // Configure the device, erase an page and the program the page. // //***************************************************************************** int main(void) { int32_t i32Res; uint32_t i; char pcStrInRam[16] = "Hello ... world!"; // // Set the clocking to run directly from the external crystal/oscillator. // (no ext 32k osc, no internal osc) // SysCtrlClockSet(false, false, SYS_CTRL_SYSDIV_32MHZ); // // Set IO clock to the same as system clock // SysCtrlIOClockSet(SYS_CTRL_SYSDIV_32MHZ); // // Erase a page // i32Res = FlashMainPageErase(PAGE_TO_ERASE_START_ADDR); ASSERT(i32Res==0); // // Program a page in chunks // for(i=0; i<PAGE_SIZE; i+=sizeof(pcStrInRam)) { i32Res = FlashMainPageProgram((uint32_t*) pcStrInRam, PAGE_TO_ERASE_START_ADDR+i, sizeof(pcStrInRam)); ASSERT(i32Res==0); } // // Loop forever // while(1) { } }
/************************************************************************************************** * @fn sbCmnd * * @brief Act on the SB command and received buffer. * * input parameters * * @param sbCmd - Received SBL command. * @param payload_len - Length of command payload * * output parameters * * None. * * @return TRUE to indicate that the SB_ENABLE_CMD command was successful; FALSE otherwise. ************************************************************************************************** */ static uint8 sbCmnd(uint8 sbCmd, uint32 payload_len) { uint32 firstAddr; uint32 lastAddr; uint32 operationLength; uint32 writeLength; uint32 respPayloadLen = 0; uint32 pageNumber; uint32 i; uint32 actual_number_of_data_bytes_to_send; uint8 paddingLength; uint8 rsp = SB_SUCCESS; uint8 imageEnabledSuccessfully = FALSE; uint8 *pBuf; pBuf = sbBuf; switch (sbCmd) { case SB_HANDSHAKE_CMD: /* Mark all pages as not-deleted-yet */ memset(pageDeleted, 0, sizeof(pageDeleted)); UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, SB_BOOTLOADER_REVISION); *pBuf++ = SB_DEVICE_TYPE_2538; UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, SB_RW_BUF_LEN ); UINT32_TO_BUF_LITTLE_ENDIAN(pBuf, SB_DEVICE_PAGE_SIZE); respPayloadLen = pBuf - sbBuf; break; case SB_WRITE_CMD: firstAddr = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf); operationLength = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf); /* The payload_len includes the addr_offset * and the operationLength fields. The value * (pBuf - sbBuf) gives the number of bytes * used by those firelds. The remaining bytes * are the actual data bytes to be written. */ writeLength = payload_len - (pBuf - sbBuf); lastAddr = firstAddr + operationLength - 1; if ((firstAddr < FLASH_BASE) || (lastAddr > CC2538_CODE_FLASH_END_ADDRESS) || (writeLength > operationLength)) { rsp = SB_FAILURE; break; } /* Before writing to a flash page for the first time during a bootloading session, the * page must be erased. The following section makes sure that every page being written * to have already been erased, otherwise, it erases it (before writing to it). * Note that the write command may span over more than a single page. */ for (pageNumber = GET_PAGE_NUMBER(firstAddr); pageNumber <= GET_PAGE_NUMBER(lastAddr); pageNumber++) { if (!IS_PAGE_ERASED(pageNumber)) { if (FlashMainPageErase(GET_PAGE_ADDRESS(pageNumber)) != 0) { rsp = SB_FAILURE; break; } MARK_PAGE_ERASED(pageNumber); } } /* Note that the start address (firstAddr) and the byte count (writeLength) must be * word aligned. The start address is expected to be already aligned (by the SBL server), * since aligning it here would require padding the buffer's start, which would require * shifting the buffer content (as the buffer is passesd as (uint32_t *pui32Data) so it * should be aligned by itself. The byte count is aligned below. */ paddingLength = ((4 - (writeLength & 0x00000003)) % 4); for (i = 0; i < paddingLength; i++) { pBuf[writeLength + i] = 0xFF; } writeLength += paddingLength; /* If the page was successfully erased (or was previously erased), perform the write action. * Note that pBuf must point to a uint32-aligned address, as required by FlashMainPageProgram(). * This is the case now (the prefixing field are total of 8 bytes), and _sbBuf is 32bit aligned. */ if ((rsp == SB_SUCCESS) && (writeLength > 0) && (FlashMainPageProgram((uint32_t *)(pBuf), firstAddr, writeLength) != 0)) { rsp = SB_FAILURE; } break; case SB_READ_CMD: firstAddr = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf); operationLength = BUF_TO_UINT32_LITTLE_ENDIAN(pBuf); lastAddr = firstAddr + operationLength - 1; if ((firstAddr < FLASH_BASE) || (lastAddr > CC2538_CODE_FLASH_END_ADDRESS) || (operationLength > sizeof(_sbBuf))) { rsp = SB_FAILURE; break; } #if !MT_SYS_OSAL_NV_READ_CERTIFICATE_DATA #if (HAL_IMG_A_BEG > HAL_NV_START_ADDR) #warning This check assumes NV PAGES located at the end of the program flash memory #endif if (GET_PAGE_NUMBER(lastAddr) >= HAL_NV_PAGE_BEG) { rsp = SB_FAILURE; break; } #endif /* If the end of the buffer is made only of 0xFF characters, no need to * send them. Find out the number of bytes that needs to be sent: */ for (actual_number_of_data_bytes_to_send = operationLength; (actual_number_of_data_bytes_to_send > 0) && ((*(uint8 *)(firstAddr + actual_number_of_data_bytes_to_send - 1)) == 0xFF); actual_number_of_data_bytes_to_send--); /* As a future upgrade, memcopy can be avoided. Instead, * may pass a pointer to the actual flash address */ (void)memcpy(pBuf, (const void *)firstAddr, actual_number_of_data_bytes_to_send); respPayloadLen = (pBuf - sbBuf) + actual_number_of_data_bytes_to_send; break; case SB_ENABLE_CMD: if (enableImg()) { imageEnabledSuccessfully = TRUE; } else { rsp = SB_VALIDATE_FAILED; } break; default: break; } sbResp(sbCmd, rsp, respPayloadLen); return imageEnabledSuccessfully; }
void flash_erase_page(uint32_t address) { FlashMainPageErase(address); }
/** * GPIO_C ISR handler. User button is GPIO_C_3 * Erases a Flash sector to trigger the bootloader backdoor */ void GPIO_C_Isr_Handler(){ IntMasterDisable(); FlashMainPageErase(CC2538_FLASH_ADDRESS); SysCtrlReset(); }
//***************************************************************************** // // Main function, setup DMA and perform flash write. Verify the transaction. // //***************************************************************************** int main(void) { uint16_t i; int32_t i32Res; // // Set the clocking to run directly from the external crystal/oscillator. // (no ext 32k osc, no internal osc) // SysCtrlClockSet(false, false, SYS_CTRL_SYSDIV_32MHZ); // // Set IO clock to the same as system clock // SysCtrlIOClockSet(SYS_CTRL_SYSDIV_32MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for Systick operation. // InitConsole(); // // Display the setup on the console. // UARTprintf("Example - Write to Flash using DMA.\n"); // // Erase Flash page that will hold our transferred data // i32Res = FlashMainPageErase(PAGE_TO_ERASE_START_ADDR); ASSERT(i32Res==0); // // Fill Source buffer (to be copied to flash) with some data // for(i=0; i<256; i++) { ucSourceBuffer[i] = '0' + (i % 10); } // // Enable the uDMA controller. // uDMAEnable(); // // Disable the uDMA channel to be used, before modifications are done. // uDMAChannelDisable(UDMA_CH2_FLASH); // // Set the base for the channel control table. // uDMAControlBaseSet(&ucDMAControlTable[0]); // // Assign the DMA channel // uDMAChannelAssign(UDMA_CH2_FLASH); // // Set attributes for the channel. // uDMAChannelAttributeDisable(UDMA_CH2_FLASH, UDMA_ATTR_HIGH_PRIORITY); // // Now set up the characteristics of the transfer. // 32-bit data size, with source increments in words (32 bits), // no destination increment. // A bus arbitration size of 1 must be used. // uDMAChannelControlSet(UDMA_CH2_FLASH, UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_NONE | UDMA_ARB_1); // // Set transfer parameters. // Source address is the location of the data to write // and destination address is the FLASH_CTRL_FWDATA register. // uDMAChannelTransferSet(UDMA_CH2_FLASH, UDMA_MODE_BASIC, ucSourceBuffer, (void *) FLASH_CTRL_FWDATA, sizeof(ucSourceBuffer)); // // Asure that the flash controller is not busy. // while(HWREG(FLASH_CTRL_FCTL) & FLASH_CTRL_FCTL_BUSY) { } // // Initialize Flash control register without changing the cache mode. // HWREG(FLASH_CTRL_FCTL) &= FLASH_CTRL_FCTL_CM_M; // // Setup Flash Address register to address of first data word (32-bit) // HWREG(FLASH_CTRL_FADDR) = PAGE_TO_ERASE_START_ADDR; // // Finally, the DMA channel must be enabled. // uDMAChannelEnable(UDMA_CH2_FLASH); // // Set FCTL.WRITE, to trigger flash write // HWREG(FLASH_CTRL_FCTL) |= FLASH_CTRL_FCTL_WRITE; // // Wait until all words has been programmed. // while( HWREG(FLASH_CTRL_FCTL) & FLASH_CTRL_FCTL_FULL ) { } // // Check if flash write was successfull // if (HWREG(FLASH_CTRL_FCTL) & FLASH_CTRL_FCTL_ABORT) { UARTprintf("Write not successful!\n"); } else { UARTprintf("Write success!\n"); } // // Set control register back to reset value without changing the cache mode. // HWREG(FLASH_CTRL_FCTL) &= FLASH_CTRL_FCTL_CM_M; // // Compare source buffer and destination flash page // if(memcmp(ucSourceBuffer, (void*) PAGE_TO_ERASE_START_ADDR, 256)==0) { UARTprintf("Buffer compares to flash page!\n"); } else { UARTprintf("Buffer does not compare to flash page!\n"); } // // We are done, loop forever // while(1) { } }