/*! * \file spi_flash.c * * \brief Target spi flash implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #include "spi_flash.h" #include "xc6xxx_hal_spi.h" /*------------------------------------------------------------------------------------ Macros -------------------------------------------------------------------------------------*/ #define FLASH_MAX_SIZE 256 * 1024 #define FLASH_MAX_PAGE_NUM (FLASH_MAX_SIZE / FLASH_PAGE_SIZE) #define TEST_BASE_ADDR 0x6400 #define TEST_START_PAGE_IDX (TEST_BASE_ADDR / FLASH_PAGE_SIZE) #define TEST_CYCLE_NUM 4u /*------------------------------------------------------------------------------------ Global Variables -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ /** * @brief spi_flash_demo * @details * @param void * @retval void */ void spi_flash_demo(void) { DEBUG("__SPI_FLASH_DEMO__\r"); SPI_TypeDef *spi_idx = XC_SPI0; // XC_SPI0;//XC_SPI1;//XC_SPI2; if (spi_idx == XC_SPI1) { GPIO_InitTypeDef gpio_cfg = {0}; gpio_cfg.Mux = GPIO_Mux0; gpio_cfg.Dir = GPIO_DIR_OUTPUT; gpio_cfg.FunSel = SSI1_CLK; gpio_cfg.Int = NOT_INT; gpio_cfg.Pull = GPIO_PULLDOWN; gpio_cfg.Pin = GPIO_14; GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = SSI1_SSN; gpio_cfg.Pin = GPIO_15; GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = SSI1_TX; gpio_cfg.Pin = GPIO_16; GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = SSI1_RX; gpio_cfg.Pin = GPIO_17; GPIO_Init(&gpio_cfg); } else if (spi_idx == XC_SPI2) { GPIO_InitTypeDef gpio_cfg = {0}; gpio_cfg.Mux = GPIO_Mux2; gpio_cfg.Dir = GPIO_DIR_OUTPUT; gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Int = NOT_INT; gpio_cfg.Pull = GPIO_PULLDOWN; gpio_cfg.Pin = GPIO_14; // clk GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Pin = GPIO_15; // ssn GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Pin = GPIO_16; GPIO_Init(&gpio_cfg); // mosi gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Pin = GPIO_17; GPIO_Init(&gpio_cfg); // miso } SPI_InitCfg_t spi_cfg = {0}; spi_cfg.Mode = SPI_MODE_MASTER; spi_cfg.DataSize = SSI_CTRL0_DFS_LEN_8BIT; spi_cfg.Direction = SSI_CTRL0_TMOD_WR; spi_cfg.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; spi_cfg.CLKPolarity = SSI_CTRL0_SCPOL_LOW; spi_cfg.CLKPhase = SPI_CPHA_LEAD; spi_cfg.FirstBit = SPI_FirstBit_MSB; xc_spi_init(spi_idx, &spi_cfg); DEBUG("SPI Start\n"); xc_spi_flash_wake_up(spi_idx); uint32_t mid = 0; spi_flash_rdid(spi_idx, (uint8_t *)&mid); DEBUG("Flash RDID: 0x%08x\n", mid); uint8_t ruid[16]; spi_flash_read_128bit_uid(spi_idx, ruid); DEBUG("Flash RUID: "); for (int i = 0; i < 16; i++) { PRINT("%02x ", ruid[i]); } PRINT("\n"); uint8_t data[FLASH_PAGE_SIZE]; #if 1 uint8_t rd_data[FLASH_PAGE_SIZE]; uint8_t cycle_num = 1; // xc_spi_flash_erase_sector(spi_idx, 0x3F000); while (cycle_num <= TEST_CYCLE_NUM) { DEBUG("---------------- %d Cycle Start ----------------\n", cycle_num); for (uint16_t n = TEST_START_PAGE_IDX; n < FLASH_MAX_PAGE_NUM; n++) { memset(data, 0x55, FLASH_PAGE_SIZE); spi_flash_erase_page(spi_idx, n * FLASH_PAGE_SIZE); DEBUG("Page 0x%x Erased.\n", n * FLASH_PAGE_SIZE); xc_spi_flash_write_page(spi_idx, n * FLASH_PAGE_SIZE, data); DEBUG("Page 0x%x has been Written.\n", n * FLASH_PAGE_SIZE); xc_spi_flash_read_page(spi_idx, n * FLASH_PAGE_SIZE, rd_data); DEBUG("Page 0x%x Read: ", n * FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { if (rd_data[i] != 0x55) DEBUG("Err: %02x\n", rd_data[i]); } memset(rd_data, 0, FLASH_PAGE_SIZE); DEBUG("--- Page 0x%x Check Complete ---\n", n * FLASH_PAGE_SIZE); } DEBUG("********** Code 0x55 Test End **********\n"); for (uint16_t n = TEST_START_PAGE_IDX; n < FLASH_MAX_PAGE_NUM; n++) { memset(data, 0xaa, FLASH_PAGE_SIZE); spi_flash_erase_page(spi_idx, n * FLASH_PAGE_SIZE); DEBUG("Page 0x%x Erased.\n", n * FLASH_PAGE_SIZE); xc_spi_flash_write_page(spi_idx, n * FLASH_PAGE_SIZE, data); DEBUG("Page 0x%x has been Written.\n", n * FLASH_PAGE_SIZE); xc_spi_flash_read_page(spi_idx, n * FLASH_PAGE_SIZE, rd_data); DEBUG("Page 0x%x Read: ", n * FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { if (rd_data[i] != 0xaa) DEBUG("Err: %02x\n", rd_data[i]); } memset(rd_data, 0, FLASH_PAGE_SIZE); DEBUG("--- Page 0x%x Check Complete ---\n", n * FLASH_PAGE_SIZE); } DEBUG("********** Code 0xAA Test End **********\n"); for (uint16_t n = TEST_START_PAGE_IDX; n < FLASH_MAX_PAGE_NUM; n++) { memset(data, 0x00, FLASH_PAGE_SIZE); spi_flash_erase_page(spi_idx, n * FLASH_PAGE_SIZE); DEBUG("Page 0x%x Erased.\n", n * FLASH_PAGE_SIZE); xc_spi_flash_write_page(spi_idx, n * FLASH_PAGE_SIZE, data); DEBUG("Page 0x%x has been Written.\n", n * FLASH_PAGE_SIZE); xc_spi_flash_read_page(spi_idx, n * FLASH_PAGE_SIZE, rd_data); DEBUG("Page 0x%x Read: ", n * FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { if (rd_data[i] != 0x00) DEBUG("Err: %02x\n", rd_data[i]); } memset(rd_data, 0, FLASH_PAGE_SIZE); DEBUG("--- Page 0x%x Check Complete ---\n", n * FLASH_PAGE_SIZE); } DEBUG("********** Code 0x00 Test End **********\n"); DEBUG("----------------- %d Cycle End -----------------\n", cycle_num); cycle_num++; } #else xc_spi_flash_erase_sector(spi_idx, 0x3F000); xc_spi_flash_read_page(spi_idx, 0x3F000, data); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { PRINT("%02x ", data[i]); } PRINT("\n"); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { data[i] = i; } // data[0] = 110; for (uint8_t i = 0; i < 16; i++) { xc_spi_flash_write_page(spi_idx, 0x3F000 + i * FLASH_PAGE_SIZE, data); data[0]++; } for (uint8_t i = 0; i < 16; i++) { memset(data, 0xff, FLASH_PAGE_SIZE); xc_spi_flash_read_page(spi_idx, 0x3F000 + i * FLASH_PAGE_SIZE, data); DEBUG("Flash Read finished%d: \n", i); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { PRINT("%02x ", data[i]); } PRINT("\n"); } uint8_t w_buff[716]; memset(w_buff, 0x11, sizeof(w_buff)); spi_write_bytes(spi_idx, 0x3F000 + 57, w_buff, sizeof(w_buff)); DEBUG("Flash Write Any finish\n"); uint8_t r_buff[1024]; spi_flash_read(spi_idx, 0x3F000, r_buff, sizeof(r_buff)); DEBUG("Flash Read Any addr: \n"); for (uint16_t i = 0; i < sizeof(r_buff); i++) PRINT("%02x ", r_buff[i]); PRINT("\n"); memset(w_buff, 0x22, sizeof(w_buff)); spi_write_bytes(spi_idx, 0x3F000 + 196, w_buff, 115); DEBUG("Flash Write Any finish2\n"); spi_flash_read(spi_idx, 0x3F000, r_buff, sizeof(r_buff)); DEBUG("Flash Read Any addr2: \n"); for (uint16_t i = 0; i < sizeof(r_buff); i++) PRINT("%02x ", r_buff[i]); PRINT("\n"); #endif } /** * @brief spi_flash_demo * @details * @param void * @retval void */ void spi_dma_flash_demo(void) { DEBUG("__SPI_DMA_FLASH_DEMO__\n"); SPI_TypeDef *spi_idx = XC_SPI0; // XC_SPI0;//XC_SPI1;//XC_SPI2; if (spi_idx == XC_SPI1) { GPIO_InitTypeDef gpio_cfg = {0}; gpio_cfg.Mux = GPIO_Mux0; gpio_cfg.Dir = GPIO_DIR_OUTPUT; gpio_cfg.FunSel = SSI1_CLK; gpio_cfg.Int = NOT_INT; gpio_cfg.Pull = GPIO_PULLDOWN; gpio_cfg.Pin = GPIO_14; GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = SSI1_SSN; gpio_cfg.Pin = GPIO_15; // GPIO_15; GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = SSI1_TX; gpio_cfg.Pin = GPIO_16; GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = SSI1_RX; gpio_cfg.Pin = GPIO_17; GPIO_Init(&gpio_cfg); } else if (spi_idx == XC_SPI2) { GPIO_InitTypeDef gpio_cfg = {0}; gpio_cfg.Mux = GPIO_Mux2; gpio_cfg.Dir = GPIO_DIR_OUTPUT; gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Int = NOT_INT; gpio_cfg.Pull = GPIO_PULLDOWN; gpio_cfg.Pin = GPIO_14; // clk GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Pin = GPIO_15; // ssn GPIO_Init(&gpio_cfg); gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Pin = GPIO_16; GPIO_Init(&gpio_cfg); // mosi gpio_cfg.FunSel = GPIO_Dx; gpio_cfg.Pin = GPIO_17; GPIO_Init(&gpio_cfg); // miso } SPI_InitCfg_t spi_cfg = {0}; spi_cfg.Mode = SPI_MODE_MASTER; spi_cfg.DataSize = SSI_CTRL0_DFS_LEN_8BIT; spi_cfg.Direction = SSI_CTRL0_TMOD_WR; spi_cfg.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // SPI_BAUDRATEPRESCALER_2; spi_cfg.CLKPolarity = SSI_CTRL0_SCPOL_LOW; spi_cfg.CLKPhase = SPI_CPHA_LEAD; spi_cfg.FirstBit = SPI_FirstBit_MSB; xc_spi_init(spi_idx, &spi_cfg); NVIC_EnableIRQ(DMA_IRQn); SPI_DMA_Flash_WakeUp(spi_idx); uint32_t mid = 0; SPI_DMA_Flash_RDID(spi_idx, (uint8_t *)&mid); // spi_flash_rdid(spi_idx, (uint8_t*)&mid); DEBUG("Flash RDID: 0x%08x\n", mid); uint8_t ruid[16]; SPI_DMA_Flash_RUID(spi_idx, ruid); // spi_flash_read_128bit_uid(spi_idx, ruid); DEBUG("Flash RUID: "); for (int i = 0; i < 16; i++) { PRINT("%02x ", ruid[i]); } PRINT("\n"); uint8_t data[FLASH_PAGE_SIZE]; #if 1 // test uint8_t rd_data[FLASH_PAGE_SIZE]; uint8_t cycle_num = 1; while (cycle_num <= TEST_CYCLE_NUM) { DEBUG("---------------- %d Cycle Start ----------------\n", cycle_num); for (uint16_t n = TEST_START_PAGE_IDX; n < FLASH_MAX_PAGE_NUM; n++) { memset(data, 0x55, FLASH_PAGE_SIZE); SPI_DMA_Flash_Erase_Page(spi_idx, n * FLASH_PAGE_SIZE); DEBUG("Page 0x%x Erased.\n", n * FLASH_PAGE_SIZE); SPI_DMA_Flash_WritePage(spi_idx, n * FLASH_PAGE_SIZE, data, FLASH_PAGE_SIZE); DEBUG("Page 0x%x has been Written.\n", n * FLASH_PAGE_SIZE); SPI_DMA_Flash_ReadPage(spi_idx, n * FLASH_PAGE_SIZE, rd_data, FLASH_PAGE_SIZE); DEBUG("Page 0x%x Read: ", n * FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { if (rd_data[i] != 0x55) DEBUG("Err: %02x\n", rd_data[i]); } memset(rd_data, 0, FLASH_PAGE_SIZE); DEBUG("--- Page 0x%x Check Complete ---\n", n * FLASH_PAGE_SIZE); } DEBUG("********** Code 0x55 Test End **********\n"); for (uint16_t n = TEST_START_PAGE_IDX; n < FLASH_MAX_PAGE_NUM; n++) { memset(data, 0xaa, FLASH_PAGE_SIZE); SPI_DMA_Flash_Erase_Page(spi_idx, n * FLASH_PAGE_SIZE); DEBUG("Page 0x%x Erased.\n", n * FLASH_PAGE_SIZE); SPI_DMA_Flash_WritePage(spi_idx, n * FLASH_PAGE_SIZE, data, FLASH_PAGE_SIZE); DEBUG("Page 0x%x has been Written.\n", n * FLASH_PAGE_SIZE); SPI_DMA_Flash_ReadPage(spi_idx, n * FLASH_PAGE_SIZE, rd_data, FLASH_PAGE_SIZE); DEBUG("Page 0x%x Read: ", n * FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { if (rd_data[i] != 0xaa) DEBUG("Err: %02x\n", rd_data[i]); } memset(rd_data, 0, FLASH_PAGE_SIZE); DEBUG("--- Page 0x%x Check Complete ---\n", n * FLASH_PAGE_SIZE); } DEBUG("********** Code 0xAA Test End **********\n"); for (uint16_t n = TEST_START_PAGE_IDX; n < FLASH_MAX_PAGE_NUM; n++) { memset(data, 0x00, FLASH_PAGE_SIZE); SPI_DMA_Flash_Erase_Page(spi_idx, n * FLASH_PAGE_SIZE); DEBUG("Page 0x%x Erased.\n", n * FLASH_PAGE_SIZE); SPI_DMA_Flash_WritePage(spi_idx, n * FLASH_PAGE_SIZE, data, FLASH_PAGE_SIZE); DEBUG("Page 0x%x has been Written.\n", n * FLASH_PAGE_SIZE); SPI_DMA_Flash_ReadPage(spi_idx, n * FLASH_PAGE_SIZE, rd_data, FLASH_PAGE_SIZE); DEBUG("Page 0x%x Read: ", n * FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { if (rd_data[i] != 0x00) DEBUG("Err: %02x\n", rd_data[i]); } memset(rd_data, 0, FLASH_PAGE_SIZE); DEBUG("--- Page 0x%x Check Complete ---\n", n * FLASH_PAGE_SIZE); } DEBUG("********** Code 0x00 Test End **********\n"); DEBUG("----------------- %d Cycle End -----------------\n", cycle_num); cycle_num++; } #else SPI_DMA_Flash_Erase_Sector(spi_idx, 0x5000); SPI_DMA_Flash_ReadPage(spi_idx, 0x5000, data, FLASH_PAGE_SIZE); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { PRINT("%02x ", data[i]); } PRINT("\n"); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { data[i] = i; } // data[0] = 110; for (uint8_t i = 0; i < 16; i++) { SPI_DMA_Flash_WritePage(spi_idx, 0x5000 + i * FLASH_PAGE_SIZE, data, FLASH_PAGE_SIZE); data[0]++; } for (uint8_t i = 0; i < 16; i++) { memset(data, 0xff, FLASH_PAGE_SIZE); SPI_DMA_Flash_ReadPage(spi_idx, 0x5000 + i * FLASH_PAGE_SIZE, data, FLASH_PAGE_SIZE); DEBUG("Flash Read finished%d: \n", i); for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++) { PRINT("%02x ", data[i]); } PRINT("\n"); } uint8_t w_buff[716]; memset(w_buff, 0x11, sizeof(w_buff)); SPI_DMA_FlashWrite(spi_idx, 0x5000 + 57, w_buff, sizeof(w_buff)); DEBUG("Flash Write Any finish\n"); uint8_t r_buff[1024]; SPI_DMA_FlashRead(spi_idx, 0x5000, r_buff, sizeof(r_buff)); DEBUG("Flash Read Any addr: \n"); for (uint16_t i = 0; i < sizeof(r_buff); i++) PRINT("%02x ", r_buff[i]); PRINT("\n"); memset(w_buff, 0x22, sizeof(w_buff)); SPI_DMA_FlashWrite(spi_idx, 0x5000 + 196, w_buff, 115); DEBUG("Flash Write Any finish2\n"); SPI_DMA_FlashRead(spi_idx, 0x5000, r_buff, sizeof(r_buff)); DEBUG("Flash Read Any addr2: \n"); for (uint16_t i = 0; i < sizeof(r_buff); i++) PRINT("%02x ", r_buff[i]); PRINT("\n"); #endif }