#include "ls1x.h" #include "ls1x_flash.h" #include "ls1x_clock.h" #include "ls1x_latimer.h" #include "Config.h" /** * @brief Erases a specified FLASH page. * @param Page_Address: The page address to be erased. * @retval None */ uint8_t Flash_pe; void FLASH_ErasePage(uint32_t Page_Address) //erase a flash page, FLASH_PAGE_SIZE { uint8_t err_code; //////////////// /////////////// assert_param(IS_FLASH_ADDRESS(Page_Address)); // FLASH->PET = 0x10; // erase time, 2.5ms FLASH->CMD = FLASH_ERASE_CMD | (Page_Address & FLASH_ADDR_MASK); err_code=FLASH_WaitForPeEnd(EraseTimeout); // FLASH_ClearIT(); } /** * @brief Erases all User FLASH pages. * @param Page_Address: The page address to be erased. * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. */ void FLASH_EraseUserFlash(uint32_t Page_Address) { uint32_t i=0; Page_Address |= LS1D_FLASH_ADDR; assert_param(IS_FLASH_ADDRESS(Page_Address)); uint32_t start_addr = Page_Address; //LS1D_FLASH_ADDR片上Flash的起始地址 uint32_t page = (0xbf01ffff - start_addr)/FLASH_PAGE_SIZE; //0xbf01ffff片上Flash的上线,计算多少页 for(i=0; i LS1D_FLASH_TOTAL) //LS1D_FLASH_TOTAL:flash大小 return -1; Page_Address |= LS1D_FLASH_ADDR; assert_param(IS_FLASH_ADDRESS(Page_Address)); ptr = (uint8_t *)Page_Address; for(i = 0; i < num; i++) { *data++ = *ptr++; } return num; } /** * @brief Write words at a specified address. * @param Page_Address: specifies the address to be programmed. * @param *data: specifies the data to be programmed. * @param num: specifies the number of data to be programmed. * @retval FLASH Status: The returned value can be: verif_correct, * verif_end, pe_end,FLASH_TIMEOUTor no_permission. */ uint8_t FLASH_WitePage(uint32_t Page_Address, uint8_t *data, uint32_t num) { uint32_t temp_flash_buf; uint8_t status; uint8_t *temp_data = data; Page_Address |= LS1D_FLASH_ADDR; //addr加上LS1D_FLASH_ADDR(0xbf000000)基地址 assert_param(IS_FLASH_ADDRESS(Page_Address)); FLASH->CMD = FLASH_PAGE_LATCH_CLEAR; //FLASH_CMD_REG=0x40000000 uint32_t flash_block_mask = FLASH_PAGE_SIZE - 1; //flash_block_mask=127(0x0000007F) uint32_t *page_data = (uint32_t *)(Page_Address & ~flash_block_mask) ; //*page_data指针指向addr地址的页地址 uint32_t *old_data = (uint32_t *)(Page_Address & ~flash_block_mask) ; //*old_data指针指向addr地址的页地址 uint32_t i, j, k, offset; j = 0; uint32_t count = num; uint32_t num_left = 0; uint32_t num_right = 0; uint32_t addr_left_align = 0xffffffff; uint32_t addr_right_align = 0xffffffff; uint32_t word_mask = WORD_WIDTH - 1; //word_mask=3 num = 0; num_left = Page_Address & word_mask; //addr=124928(0x1E800),word_mask=3(0x00003),addr& word_mask=0 if (num_left) //假如num_left=3 { num_left = WORD_WIDTH - num_left; //num_left=1 num++; //num=1 addr_left_align = (Page_Address & flash_block_mask) >> 2; //addr_left_align更改为操作地址低8位区0右移2位 } j = count - num_left; //j=操作起始地址 num_right = (j & word_mask); if (num_right) { num++; addr_right_align = Page_Address + count - num_right; addr_right_align = (addr_right_align & flash_block_mask) >> 2; } j = count - num_left - num_right; j = j >> 2; num += j; offset = ((Page_Address & flash_block_mask)>>2); for(j=0, i=0; i<(FLASH_PAGE_SIZE/4); i++) { if( (offset <= i) && (j < num) ) { if (i == addr_left_align) { int m = 0; temp_flash_buf = old_data[i]; k = 1 << ((WORD_WIDTH - num_left) * 8); temp_flash_buf &= (k - 1); for (m = 0; m < num_left; m++) { temp_flash_buf |= temp_data[m] << (WORD_WIDTH - num_left + m)*8; } temp_data = temp_data + num_left; //address change to be logic 0 again. page_data[i] = temp_flash_buf; num--; //because j don't add 1, num has to sub 1. } else if (i == addr_right_align) { temp_flash_buf = old_data[i]; k = 1 << (num_right * 8); temp_flash_buf &= ~(k - 1); for (k = 0; k < num_right; k++) { temp_flash_buf |= temp_data[j*4+k] << k*8; } j++; page_data[i] = temp_flash_buf; } else { temp_flash_buf = 0; for (k = 0; k < WORD_WIDTH; k++) { temp_flash_buf |= temp_data[j*4+k] << k*8; } j++; page_data[i] = temp_flash_buf; } } else page_data[i] = old_data[i]; } Flash_pe=0; FLASH_ErasePage(Page_Address); //erase a flash page, FLASH_PAGE_SIZE FLASH->CMD = FLASH_WRITE_CMD | (Page_Address & FLASH_ADDR_MASK) ; status=FLASH_WaitForPeEnd(ProgramTimeout); return status; } /** * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. * @param Timeout: FLASH programming Timeout * @retval FLASH Status: The returned value can be: verif_correct, * verif_end, pe_end,FLASH_TIMEOUTor no_permission. */ uint8_t FLASH_WaitForPeEnd(uint32_t Timeout) { uint8_t status; /* Check for the Flash Status */ /* Wait for a Flash operation to complete or a TIMEOUT to occur */ status = FLASH_GetStatus(); while((Timeout != 0x00)&& ((status & 0x04)==0x00)) { // (status != pe_end) && status = FLASH_GetStatus(); status = FLASH_GetStatus(); delay_ms(1); Timeout--; } if(Timeout == 0x00 ) { status = FLASH_TIMEOUT; } /* Return the operation status */ return status; } /** * @brief Checks whether the specified FLASH flag is set or not. * @retval The new state of FLASH_FLAG (SET or RESET). */ uint8_t FLASH_GetStatus(void) { uint8_t status; status=(FLASH->STS & 0x0F); return status; } /** * @brief Checks whether the specified FLASH flag is set or not. * @param FLASH_FLAG: specifies the FLASH flag to check. * This parameter can be one of the following values: * @arg FLASH_FLAG_VERIFCORRECT: Verify Correct flag * @arg FLASH_FLAG_VERIFEND: Verify End flag * @arg FLASH_FLAG_PEEND: Pe End flag * @arg FLASH_FLAG_NOPERMISSION: No Permission flag * @retval The new state of FLASH_FLAG (SET or RESET). */ FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG) { ITStatus bitstatus = RESET; assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)) ; if((FLASH->STS & FLASH_FLAG) != (uint32_t)RESET) { bitstatus = SET; } else { bitstatus = RESET; } return bitstatus; } /** * @brief Enables or disables the specified FLASH interrupts. * @param NewState: new state of the specified Flash interrupts. * This parameter can be: ENABLE or DISABLE. * @retval None */ void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_FLASH_CONFIG_IT(FLASH_IT)); assert_param(IS_FUNCTIONAL_STATE(NewState)); (NewState != DISABLE)? (SET_BIT(FLASH->PET,FLASH_IT)) : (CLEAR_BIT(FLASH->PET,FLASH_IT)); } /** * @brief Enables or disables the FLASH interrupts. * @param NewState: new state of the specified Flash interrupts. * This parameter can be: ENABLE or DISABLE. * @retval None */ void FLASH_ITCmd(FunctionalState NewState) { assert_param(IS_FUNCTIONAL_STATE(NewState)); (NewState != DISABLE)? (SET_BIT(INT->INTC_EN,IRQ_FLASH)) : (CLEAR_BIT(INT->INTC_EN,IRQ_FLASH)); //清除中断标记位 } /** * @brief Clears the FLASH's interrupt flag. * @retval None */ void FLASH_ClearIT(void) { /* clear data reg*/ SET_BIT(FLASH->CMD , FLASH_INT_CLEAR); #if !defined (LS1C103) SET_BIT(INT->INTC_CLR,IRQ_FLASH); //清除中断标记位 #endif } /** *@brief Example of FLASH Write. *retval None */ void FLASH_WiteTest(uint32_t Page_Address,uint8_t Page_data) { uint8_t temp[128]={0}; uint32_t USER_BEGIN = Page_Address; FLASH_Status status; int i; for(i=0;i<128;i++) temp[i] = Page_data; Flash_pe=0; status=FLASH_WitePage(USER_BEGIN, temp, FLASH_PAGE_SIZE); } /** *@brief Example of FLASH Read. *retval None */ void FLASH_ReadTest(uint32_t Page_Address) { uint8_t temp[128]={0}; uint32_t USER_BEGIN = Page_Address; int i; FLASH_ReadPage(USER_BEGIN,temp,FLASH_PAGE_SIZE); for(i=0;i<128;i++) { if(i%9 == 0) printf("\r\n"); printf("%02x ",temp[i]); //十六进制输出 } }