From 46e9db079616d46c7d6bfc8529e854df1b7788aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E7=90=AA?= Date: Wed, 29 Jul 2026 11:27:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=B8=AD=E6=80=A7=E5=85=89?= =?UTF-8?q?=E5=86=99flash=E9=97=AA=E7=83=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Drivers/xc_driver/xc_drv_fmc_spi.c | 38 +++++++++- .../Drivers/xc_driver/xc_drv_fmc_spi.h | 1 + .../example/ble/ble_peripheral/app/src/Mode.c | 11 +++ .../example/ble/ble_peripheral/app/src/PWM.h | 3 + .../ble/ble_peripheral/app/src/bridge_pwm.c | 64 ++++++++++++++++ .../app/src/ota_flash_interface.c | 76 ++++++++++++++++--- .../app/src/ota_flash_interface.h | 4 +- 7 files changed, 181 insertions(+), 16 deletions(-) diff --git a/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.c b/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.c index 2b89b25..4c27df2 100644 --- a/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.c +++ b/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.c @@ -340,6 +340,10 @@ __RAM_CODE static uint8_t xc_fmc_spi_flash_status(void) return sta[1]; } +__RAM_CODE __WEAK void xc_fmc_spi_flash_busy_hook(void) +{ +} + /** **************************************************************************************** * @brief xc_fmc_spi_flash_wait_busy @@ -354,8 +358,14 @@ __RAM_CODE static uint8_t xc_fmc_spi_flash_status(void) */ __RAM_CODE static void xc_fmc_spi_flash_wait_busy(void) { - while ((xc_fmc_spi_flash_status() & PUYA_FLASH_STATUS_WIP_SET)) - ; + for (;;) { + xc_fmc_spi_flash_busy_hook(); + if ((xc_fmc_spi_flash_status() & + PUYA_FLASH_STATUS_WIP_SET) == 0U) + break; + } + + xc_fmc_spi_flash_busy_hook(); } /** @@ -472,6 +482,30 @@ __RAM_CODE void xc_fmc_spi_flash_erase_page(uint32_t addr) * @retval void **************************************************************************************** */ +__RAM_CODE void xc_fmc_spi_flash_write_16bytes(uint32_t addr, uint8_t *data) +{ + uint8_t cmd[16 + 4] = {0}; + + xc_fmc_spi_flash_wait_busy(); + xc_fmc_spi_flash_write_enable(); + xc_fmc_spi_flash_wait_busy(); + + cmd[0] = CMD_PAGE_PROGRAM; + cmd[1] = addr >> 16; + cmd[2] = addr >> 8; + cmd[3] = addr; + + ram_memcpy_bytes(&cmd[4], data, 16); + + xc_fmc_status_wait_idle(); + + xc_fmc_spi_enable(FMC_SSI_CTRL0_DFS_LEN_32BIT); + xc_fmc_spi_write_nbyte(cmd, sizeof(cmd)); + + xc_fmc_spi_flash_wait_busy(); + xc_fmc_spi_disable(); +} + __RAM_CODE void xc_fmc_spi_flash_write_page(uint32_t addr, uint8_t *data, uint16_t size) { diff --git a/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.h b/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.h index 54c1e09..39c1df5 100644 --- a/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.h +++ b/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_fmc_spi.h @@ -293,6 +293,7 @@ void xc_fmc_spi_flash_wait_busy(void); void xc_fmc_spi_flash_write_enable(void); void xc_fmc_spi_flash_erase_sector(uint32_t addr); void xc_fmc_spi_flash_erase_page(uint32_t addr); +void xc_fmc_spi_flash_write_16bytes(uint32_t addr, uint8_t *data); void xc_fmc_spi_flash_write_page(uint32_t addr, uint8_t *buff, uint16_t size); void xc_fmc_spi_flash_read_page(uint32_t addr, uint8_t *buff, diff --git a/project/example/ble/ble_peripheral/app/src/Mode.c b/project/example/ble/ble_peripheral/app/src/Mode.c index c94a739..e03fde8 100644 --- a/project/example/ble/ble_peripheral/app/src/Mode.c +++ b/project/example/ble/ble_peripheral/app/src/Mode.c @@ -121,6 +121,17 @@ void set_mode(){ { Light_Transition_BeginModeChange(); } + else if(choose_mode_falsg == CUSTOM_TEMPERATURE_MODE) + { + /* + * APP CCT packets can arrive continuously while the color + * ring is dragged. Restart the same 200 ms linear transition + * used by static mode changes from the current visible + * output, so the latest W/C target is followed without a + * discontinuity. + */ + Light_Transition_BeginModeChange(); + } else { Light_Transition_ModeActive=0U; diff --git a/project/example/ble/ble_peripheral/app/src/PWM.h b/project/example/ble/ble_peripheral/app/src/PWM.h index 272ba68..ae7c830 100644 --- a/project/example/ble/ble_peripheral/app/src/PWM.h +++ b/project/example/ble/ble_peripheral/app/src/PWM.h @@ -147,6 +147,9 @@ void Bridge_Init(void); void Bridge_Off(void); void Bridge_Service_1ms(void); void Bridge_Deadtime_Expired(void); +void Bridge_FlashBlank_Request(void); +uint8_t Bridge_FlashBlank_Ready(void); +void Bridge_FlashBlank_Resume(void); #ifdef __cplusplus } #endif diff --git a/project/example/ble/ble_peripheral/app/src/bridge_pwm.c b/project/example/ble/ble_peripheral/app/src/bridge_pwm.c index 2faf280..f9ba3bf 100644 --- a/project/example/ble/ble_peripheral/app/src/bridge_pwm.c +++ b/project/example/ble/ble_peripheral/app/src/bridge_pwm.c @@ -54,9 +54,14 @@ #define BRIDGE_STAGE_START_C 4U #define BRIDGE_STAGE_END_C 5U +#define BRIDGE_FLASH_BLANK_IDLE 0U +#define BRIDGE_FLASH_BLANK_REQUEST 1U +#define BRIDGE_FLASH_BLANK_READY 2U + static volatile uint8_t active_state; static volatile uint8_t output_mode; static volatile uint8_t timer_stage; +static volatile uint8_t flash_blank_state; static volatile uint8_t pending_single_state; static volatile uint16_t pending_single_duty; static volatile uint16_t frame_w_us; @@ -212,6 +217,7 @@ void Bridge_Init(void) NVIC_SetPriority((IRQn_Type)TIMER3_IRQn, 0); NVIC_EnableIRQ(TIMER3_IRQn); + flash_blank_state = BRIDGE_FLASH_BLANK_IDLE; bridge_ready = 1U; Bridge_Off(); } @@ -244,6 +250,57 @@ void Bridge_Off(void) cached_c_mix = 0xFFFFU; bridge_force_off(); output_mode = BRIDGE_MODE_OFF; + + if (flash_blank_state == BRIDGE_FLASH_BLANK_REQUEST) + flash_blank_state = BRIDGE_FLASH_BLANK_READY; +} + +void Bridge_FlashBlank_Request(void) +{ + if (!bridge_ready || + flash_blank_state != BRIDGE_FLASH_BLANK_IDLE) + return; + + if (output_mode == BRIDGE_MODE_DUAL && + timer_stage != BRIDGE_STAGE_IDLE) { + flash_blank_state = BRIDGE_FLASH_BLANK_REQUEST; + return; + } + + flash_blank_state = BRIDGE_FLASH_BLANK_READY; +} + +uint8_t Bridge_FlashBlank_Ready(void) +{ + return (flash_blank_state == BRIDGE_FLASH_BLANK_READY) ? 1U : 0U; +} + +void Bridge_FlashBlank_Resume(void) +{ + if (flash_blank_state != BRIDGE_FLASH_BLANK_READY) + return; + + flash_blank_state = BRIDGE_FLASH_BLANK_IDLE; +} + +/* + * Flash page-program keeps global interrupts disabled. Poll Timer3 from the + * RAM-resident Flash busy loop so the software H-bridge frame continues. + */ +__RAM_CODE void xc_fmc_spi_flash_busy_hook(void) +{ + if (!bridge_ready || + (deviceStatus == POWEROFF && !Light_Transition_FadeActive) || + output_mode != BRIDGE_MODE_DUAL || + timer_stage < BRIDGE_STAGE_START_W || + timer_stage > BRIDGE_STAGE_END_C) + return; + + if (timer_tis_get(TIMER3_IDX) != 0U) { + NVIC_ClearPendingIRQ((IRQn_Type)TIMER3_IRQn); + (void)timer_tic_get(TIMER3_IDX); + Bridge_Deadtime_Expired(); + } } __RAM_CODE void Bridge_Deadtime_Expired(void) @@ -260,6 +317,10 @@ __RAM_CODE void Bridge_Deadtime_Expired(void) } if (timer_stage == BRIDGE_STAGE_START_W) { + if (flash_blank_state == BRIDGE_FLASH_BLANK_REQUEST) { + flash_blank_state = BRIDGE_FLASH_BLANK_READY; + } + /* * Latch all four durations together at the W boundary. A brightness * update can then never mix old and new timings inside one frame. @@ -355,6 +416,9 @@ __RAM_CODE void Bridge_Service_1ms(void) uint16_t pwm_duty; uint8_t single_state; + if (flash_blank_state != BRIDGE_FLASH_BLANK_IDLE) + return; + if (!bridge_ready || (deviceStatus == POWEROFF && !Light_Transition_FadeActive)) { if (output_mode != BRIDGE_MODE_OFF || timer_stage != BRIDGE_STAGE_IDLE) { diff --git a/project/example/ble/ble_peripheral/app/src/ota_flash_interface.c b/project/example/ble/ble_peripheral/app/src/ota_flash_interface.c index 84eeeff..8763d38 100644 --- a/project/example/ble/ble_peripheral/app/src/ota_flash_interface.c +++ b/project/example/ble/ble_peripheral/app/src/ota_flash_interface.c @@ -4,6 +4,14 @@ // extern uint8_t ble_flash_operation_can_check(void); #include "ota_protocol.h" #include "fmc_spi.h" +#include "PWM.h" + +#define USER_DATA_FLASH_ADDR 0x1E000UL +#define USER_FLASH_WRITE_CHUNKS 16U +#define USER_FLASH_CHUNK_GAP_MS 20U +static uint8_t user_flash_write_chunk; +static uint8_t user_flash_chunk_gap_ms; + op_flash_t op_flash = { OP_IDEL, }; @@ -62,9 +70,43 @@ void ble_flash_handle(void) { // LOGI("FMC_SPI_Flash_WritePage: op_flash.op_addr=%x\n", // op_flash.op_addr); - GLOBAL_INT_DISABLE(); - FMC_SPI_Flash_WritePage(op_flash.op_addr, op_flash.op_buff, 256); - GLOBAL_INT_RESTORE(); + if(op_flash.op_addr == USER_DATA_FLASH_ADDR) + { + if(user_flash_chunk_gap_ms != 0U) + { + user_flash_chunk_gap_ms--; + return; + } + + uint32_t chunk_offset = + (uint32_t)user_flash_write_chunk * 16U; + + Bridge_FlashBlank_Request(); + if(Bridge_FlashBlank_Ready() == 0U) + return; + + GLOBAL_INT_DISABLE(); + FMC_SPI_Flash_Write16Bytes( + op_flash.op_addr + chunk_offset, + &op_flash.op_buff[chunk_offset]); + GLOBAL_INT_RESTORE(); + Bridge_FlashBlank_Resume(); + + user_flash_write_chunk++; + if(user_flash_write_chunk < USER_FLASH_WRITE_CHUNKS) { + user_flash_chunk_gap_ms = USER_FLASH_CHUNK_GAP_MS; + return; + } + + user_flash_write_chunk = 0U; + user_flash_chunk_gap_ms = 0U; + } + else + { + GLOBAL_INT_DISABLE(); + FMC_SPI_Flash_WritePage(op_flash.op_addr, op_flash.op_buff, 256); + GLOBAL_INT_RESTORE(); + } op_flash.op_state = OP_IDEL; app_op_flash_flag = 2; @@ -83,9 +125,20 @@ void ble_flash_handle(void) } } else if (op_flash.op_state == OP_WIAT_PAGE_ERASE) { { + if(op_flash.op_addr == USER_DATA_FLASH_ADDR) { + Bridge_FlashBlank_Request(); + if(Bridge_FlashBlank_Ready() == 0U) + return; + } + GLOBAL_INT_DISABLE(); FMC_SPI_Flash_Erase_Page(op_flash.op_addr); GLOBAL_INT_RESTORE(); + if(op_flash.op_addr == USER_DATA_FLASH_ADDR) { + Bridge_FlashBlank_Resume(); + user_flash_write_chunk = 0U; + user_flash_chunk_gap_ms = 0U; + } op_flash.op_state = OP_IDEL; app_op_flash_flag = 1; } @@ -98,15 +151,14 @@ uint8_t app_data[FLASH_PAGE_SIZE] = {0}; void app_op_flash(void) { - if(op_flash.op_state == OP_IDEL&&app_op_flash_flag ==0) - { - ble_flash_later_page_erase(0x1E000); - } - else if(op_flash.op_state == OP_IDEL &&app_op_flash_flag ==1) - { - ble_flash_later_write_page(app_data,0x1E000); - - } + if(op_flash.op_state == OP_IDEL && app_op_flash_flag == 0U) + { + ble_flash_later_page_erase(USER_DATA_FLASH_ADDR); + } + else if(op_flash.op_state == OP_IDEL && app_op_flash_flag == 1U) + { + ble_flash_later_write_page(app_data, USER_DATA_FLASH_ADDR); + } } extern uint8_t aa; diff --git a/project/example/ble/ble_peripheral/app/src/ota_flash_interface.h b/project/example/ble/ble_peripheral/app/src/ota_flash_interface.h index a594dcd..45456d5 100644 --- a/project/example/ble/ble_peripheral/app/src/ota_flash_interface.h +++ b/project/example/ble/ble_peripheral/app/src/ota_flash_interface.h @@ -7,7 +7,9 @@ #endif // (USE_ROM_FLASH) #endif // !(USE_XIP) #include +void xc_fmc_spi_flash_write_16bytes(uint32_t addr, uint8_t *data); #define FMC_SPI_Flash_WritePage xc_fmc_spi_flash_write_page +#define FMC_SPI_Flash_Write16Bytes xc_fmc_spi_flash_write_16bytes #define FMC_SPI_Flash_ReadPage xc_fmc_spi_flash_read_page #define FMC_SPI_Flash_Erase_Sector FMC_SPI_Flash_Erase_Sector #define FMC_SPI_Flash_Erase_Page xc_fmc_spi_flash_erase_page @@ -42,5 +44,3 @@ int ble_flash_later_write_page(uint8_t *buff, uint32_t PageAddR); int ble_flash_later_sector_erase(uint32_t addr); #endif // __OTA_FLASH_INTERFACE_H_ - -