#include "stm32f4xx_flash.h" #include "stm32f4xx.h" #include "modbus_parse.h" #include "modbus_flash.h" #include "string.h" #include "os.h" extern uint8_t ModbusCoil[1250]; extern uint16_t ModbusReg[10000]; extern uint8_t ModbusErr; extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/ uint8_t ModbusFlashWrite(void); uint8_t ModbusErrReply(uint8_t func, uint8_t err); /*flash写入任务*/ void AppTaskModbusWriteFlash(void *p_arg) { OS_ERR err; while(1) { OSSemPend(ModbusWriteFlash, 0, &err); while(1) { /*清除多余嵌套的信号量*/ while(OSSemAccept(ModbusWriteFlash) > 0); OSSemPend(ModbusWriteFlash, OS_TICKS_PER_SEC * 2, &err); /*当连续2s未收到信号量时,退出循环*/ if (err == OS_ERR_TIMEOUT) { break; } /*出现错误退出循环,防止阻塞*/ if (err != OS_ERR_NONE) { break; } } /*当因为错误退出循环时,不进行flash写入*/ if (err != OS_ERR_TIMEOUT) { continue; } /*只有当连续2s未收到信号量时才进行写入操作,防止信号量嵌套导致重复写入延迟*/ //ModbusErr = ModbusFlashWrite(); } } uint8_t ModbusFlashWrite(void) { uint32_t addres = MODBUS_FLASH_COIL_ADDR; uint16_t halfWord; FLASH_Status status; FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); /*扇区擦除,写入之前必须先擦除*/ status = FLASH_EraseSector(MODBUS_FLASH_SECTOR, VoltageRange_3); if(status != FLASH_COMPLETE) { return ERR_SLAVE; } for(uint16_t i = 0; i < 1250; i += 2) { /*前面的放在低字节,后面的放在高字节*/ halfWord = ((uint16_t)ModbusCoil[i + 1] << 8) | ((uint16_t)ModbusCoil[i]); status = FLASH_ProgramHalfWord(addres, halfWord); /*写入失败,停止写入*/ if(status != FLASH_COMPLETE) { return ERR_SLAVE; } addres += 2; } addres = MODBUS_FLASH_REG_ADDR; for(uint16_t i = 0; i < 10000; i++) { status = FLASH_ProgramHalfWord(addres, ModbusReg[i]); /*写入失败,停止写入*/ if(status != FLASH_COMPLETE) { return ERR_SLAVE; } addres += 2; } FLASH_Lock(); return 0; } void ModbusRegReadFlash(void) { memcpy(ModbusReg, (const void *)MODBUS_FLASH_REG_ADDR, sizeof(ModbusReg)); } void ModbusCoilReadFlash(void) { memcpy(ModbusCoil, (const void *)MODBUS_FLASH_COIL_ADDR, sizeof(ModbusCoil)); }