|
|
@@ -1,350 +0,0 @@ |
|
|
|
/** |
|
|
|
* @file modbus_operate_module.c |
|
|
|
* @author zhangcheng |
|
|
|
* @brief modbus请求操作处理模块源文件 |
|
|
|
* @version v0.1 |
|
|
|
* @date 2025-07-25 |
|
|
|
* |
|
|
|
* @copyright Copyright (c) 2025 |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include "../../SYSTEM/inc/system.h" |
|
|
|
#include "../inc/modbus_operate_module.h" |
|
|
|
#include "../inc/modbus_request_module.h" |
|
|
|
#include "../inc/modbus_ack_module.h" |
|
|
|
#include "../inc/CRC16.h" |
|
|
|
|
|
|
|
#define OPERATE_PROC_MODULE_PRIO 3 |
|
|
|
#define OPERATE_PROC_MODULE_STACK_SIZE 1024 |
|
|
|
static CPU_STK OperateProcModuleStack[OPERATE_PROC_MODULE_STACK_SIZE]; |
|
|
|
static OS_TCB OperateProcModuleTcb; |
|
|
|
static OS_Q AckQueue; |
|
|
|
static void OperateProcModuleTask(void * pArg); |
|
|
|
|
|
|
|
static uint16_t FlashBuffer[10000]; |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 操作处理模块初始化 |
|
|
|
* @details |
|
|
|
* |
|
|
|
* @param[in] 无 |
|
|
|
* |
|
|
|
* @return RESUIL 初始化结果 |
|
|
|
* @retval MODBUS_TURE 成功 |
|
|
|
* @retval MODBUS_FALSE 失败 |
|
|
|
*/ |
|
|
|
RESUIL OperateProcModuleInit(void) |
|
|
|
{ |
|
|
|
OS_ERR err; |
|
|
|
|
|
|
|
CPU_SR_ALLOC(); |
|
|
|
CPU_CRITICAL_ENTER(); |
|
|
|
|
|
|
|
OSTaskCreate( (OS_TCB * )&OperateProcModuleTcb, |
|
|
|
(CPU_CHAR * )"OperateProcModule", |
|
|
|
(OS_TASK_PTR )OperateProcModuleTask, |
|
|
|
(void * )0, |
|
|
|
(OS_PRIO )OPERATE_PROC_MODULE_PRIO, |
|
|
|
(CPU_STK * )OperateProcModuleStack, |
|
|
|
(CPU_STK_SIZE )OPERATE_PROC_MODULE_STACK_SIZE / 10, |
|
|
|
(CPU_STK_SIZE )OPERATE_PROC_MODULE_STACK_SIZE, |
|
|
|
(OS_MSG_QTY )0, |
|
|
|
(OS_TICK )0, |
|
|
|
(void * )0, |
|
|
|
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), |
|
|
|
(OS_ERR * )&err); |
|
|
|
if(err != OS_ERR_NONE) |
|
|
|
{ |
|
|
|
MODBUS_LOG("OperateProcModule init fail\r\n"); |
|
|
|
return MODBUS_FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
OSQCreate(&AckQueue, "AckQueue", 1, &err); |
|
|
|
if(err != OS_ERR_NONE) |
|
|
|
{ |
|
|
|
MODBUS_LOG("OperateProcModule data queue create fail\r\n"); |
|
|
|
OSTaskDel(&OperateProcModuleTcb, &err); |
|
|
|
return MODBUS_FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
CPU_CRITICAL_EXIT(); |
|
|
|
|
|
|
|
return MODBUS_TURE; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 请求帧处理模块 |
|
|
|
* @details |
|
|
|
* |
|
|
|
* @param[in] *pArg 任务参数 |
|
|
|
* |
|
|
|
* @return RESUIL 初始化结果 |
|
|
|
* @retval MODBUS_TURE 成功 |
|
|
|
* @retval MODBUS_FALSE 失败 |
|
|
|
*/ |
|
|
|
static void OperateProcModuleTask(void *pArg) |
|
|
|
{ |
|
|
|
OS_ERR err = OS_ERR_NONE; |
|
|
|
|
|
|
|
REQUEST_FRAME requestFrame; |
|
|
|
ACK_FRAME ackFrame; |
|
|
|
RESUIL res; |
|
|
|
|
|
|
|
uint8_t *pCoil = (uint8_t *)COIL_REGISTER_ADRR; |
|
|
|
uint16_t *pDataRegister = (uint16_t *)DATA_REGISTER_ADRR; |
|
|
|
uint16_t *pKeepRegister = (uint16_t *)KEEP_REGISTER_ADRR; |
|
|
|
|
|
|
|
while(1) |
|
|
|
{ |
|
|
|
/* 阻塞式接收请求数据帧 */ |
|
|
|
res = RequestOperateDataRead(&requestFrame, 0); |
|
|
|
|
|
|
|
if (res != MODBUS_TURE) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
ackFrame.deviceNumber = requestFrame.deviceNumber; |
|
|
|
ackFrame.functionCode = requestFrame.functionCode; |
|
|
|
|
|
|
|
switch (requestFrame.functionCode) |
|
|
|
{ |
|
|
|
case READ_COIL: |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_READ; |
|
|
|
ackFrame.operateObjType = OPERATE_COIL; |
|
|
|
ackFrame.format = MODBUS_STANDARD; |
|
|
|
ackFrame.returnByteCount = requestFrame.readCount / 8; |
|
|
|
ackFrame.data = pCoil + (requestFrame.memoryAddr / 8); |
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
break; |
|
|
|
} |
|
|
|
case READ_KEEP_REGISTER: |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_READ; |
|
|
|
ackFrame.operateObjType = OPERATE_REGISTER; |
|
|
|
ackFrame.format = MODBUS_STANDARD; |
|
|
|
ackFrame.returnByteCount = requestFrame.readCount * 2; |
|
|
|
|
|
|
|
if ( requestFrame.memoryAddr < 0x270F) |
|
|
|
{ |
|
|
|
ackFrame.data = (uint8_t *)(pDataRegister + requestFrame.memoryAddr); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
requestFrame.memoryAddr -= 0xA080; |
|
|
|
//ackFrame.data = (uint8_t *)(pKeepRegister + requestFrame.memoryAddr); |
|
|
|
ackFrame.data = (uint8_t *)(FlashBuffer + requestFrame.memoryAddr); |
|
|
|
} |
|
|
|
|
|
|
|
//ackFrame.data = (uint8_t *)(pKeepRegister + requestFrame.memoryAddr); |
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
break; |
|
|
|
} |
|
|
|
case WRITE_ONE_COIL: |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_WRITE; |
|
|
|
ackFrame.operateObjType = OPERATE_COIL; |
|
|
|
ackFrame.format = MODBUS_STANDARD; |
|
|
|
ackFrame.returnByteCount = requestFrame.readCount; |
|
|
|
ackFrame.memoryAddr = requestFrame.memoryAddr; |
|
|
|
ackFrame.data = pCoil + (requestFrame.memoryAddr / 8); |
|
|
|
|
|
|
|
if (requestFrame.data[0] == 0xFF) |
|
|
|
{ |
|
|
|
*ackFrame.data |= (0x01 << (requestFrame.memoryAddr % 8)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
*ackFrame.data &= ~(0x01 << (requestFrame.memoryAddr % 8)); |
|
|
|
} |
|
|
|
|
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
case WRITE_COIL: |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_WRITE; |
|
|
|
ackFrame.operateObjType = OPERATE_COIL; |
|
|
|
ackFrame.format = MODBUS_STANDARD; |
|
|
|
ackFrame.returnByteCount = requestFrame.writeCount; |
|
|
|
ackFrame.memoryAddr = requestFrame.memoryAddr; |
|
|
|
ackFrame.data = pCoil + (requestFrame.memoryAddr / 8); |
|
|
|
|
|
|
|
uint8_t offset = requestFrame.memoryAddr % 8; |
|
|
|
|
|
|
|
for (uint16_t i = 0; i < requestFrame.writeByteLenght; i++) |
|
|
|
{ |
|
|
|
for (uint8_t j = 0; j < 8; j++) |
|
|
|
{ |
|
|
|
if (*requestFrame.data & (0x01 << j)) |
|
|
|
{ |
|
|
|
*ackFrame.data |= (1 << offset); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
*ackFrame.data &= ~(1 << offset); |
|
|
|
} |
|
|
|
offset++; |
|
|
|
if (offset == 8) |
|
|
|
{ |
|
|
|
offset = 0; |
|
|
|
ackFrame.data++; |
|
|
|
} |
|
|
|
} |
|
|
|
requestFrame.data++; |
|
|
|
} |
|
|
|
|
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
break; |
|
|
|
} |
|
|
|
case WRITE_KEEP_REGISTER: |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_WRITE; |
|
|
|
ackFrame.operateObjType = OPERATE_REGISTER; |
|
|
|
ackFrame.format = MODBUS_STANDARD; |
|
|
|
ackFrame.returnByteCount = requestFrame.writeCount; |
|
|
|
ackFrame.memoryAddr = requestFrame.memoryAddr; |
|
|
|
|
|
|
|
if ( requestFrame.memoryAddr < 0x270F) |
|
|
|
{ |
|
|
|
ackFrame.data = (uint8_t *)(pDataRegister + requestFrame.memoryAddr); |
|
|
|
|
|
|
|
for (uint16_t i = 0; i < requestFrame.writeCount; i++) |
|
|
|
{ |
|
|
|
((uint16_t *)ackFrame.data)[i] = (requestFrame.data[2*i] << 8) | requestFrame.data[2*i+1]; |
|
|
|
} |
|
|
|
|
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
requestFrame.memoryAddr -= 0xA080; |
|
|
|
//ackFrame.data = (uint8_t *)(pKeepRegister + requestFrame.memoryAddr); |
|
|
|
ackFrame.data = (uint8_t *)(FlashBuffer + requestFrame.memoryAddr); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FLASH_Unlock(); |
|
|
|
FLASH_DataCacheCmd(ENABLE); |
|
|
|
|
|
|
|
memcpy((void *)FlashBuffer, (void *)KEEP_REGISTER_ADRR, KEEP_REGISTER_SIZE); |
|
|
|
|
|
|
|
while (FLASH_GetStatus() != FLASH_COMPLETE); |
|
|
|
|
|
|
|
for (uint16_t i = 0; i < requestFrame.writeCount; i++) |
|
|
|
{ |
|
|
|
FlashBuffer[requestFrame.memoryAddr + i] = (requestFrame.data[2*i] << 8) | requestFrame.data[2*i+1]; |
|
|
|
} |
|
|
|
|
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
|
|
|
|
// FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3); |
|
|
|
for (uint16_t i = 0; i < KEEP_REGISTER_SIZE / 2; i++) |
|
|
|
{ |
|
|
|
// FLASH_ProgramHalfWord((uint32_t)KEEP_REGISTER_ADRR + 2 * i, FlashBuffer[i]); |
|
|
|
while (FLASH_GetStatus() != FLASH_COMPLETE); |
|
|
|
} |
|
|
|
|
|
|
|
FLASH_DataCacheCmd(ENABLE); |
|
|
|
FLASH_Lock(); |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
case READ_OUT_SCOPE_REGISTER: //0x10000 ~ 0x1A000 40KB |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_READ; |
|
|
|
ackFrame.operateObjType = OPERATE_REGISTER; |
|
|
|
ackFrame.format = MODBUS_EXT; |
|
|
|
ackFrame.returnByteCount = requestFrame.readCount * 2; |
|
|
|
ackFrame.data = (uint8_t *)((DATA_REGISTER_ADRR + DATA_REGISTER_NUMBER) + requestFrame.extMemoryAddr - 0x10000); |
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
break; |
|
|
|
} |
|
|
|
case READ_ALL_SINGULAR_REGISTER: |
|
|
|
{ |
|
|
|
ackFrame.operateType = OPERATE_READ; |
|
|
|
ackFrame.operateObjType = OPERATE_REGISTER; |
|
|
|
ackFrame.format = MODBUS_STANDARD; |
|
|
|
ackFrame.returnByteCount = 0xFFFF; |
|
|
|
ackFrame.memoryAddr = requestFrame.memoryAddr; |
|
|
|
ackFrame.data = (uint8_t *)(pDataRegister + requestFrame.memoryAddr); |
|
|
|
ackFrame.errorCode = ERROR_NONE; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
break; |
|
|
|
} |
|
|
|
case READ_CORRESPONDENCE_HISTORY: |
|
|
|
{ |
|
|
|
ackFrame.data = (uint8_t *)0x08020000; |
|
|
|
OSQPost(&AckQueue, &ackFrame, 1, |
|
|
|
OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED, &err); |
|
|
|
AckProcModuleSetFlags(NORMAL_FLAG_BIT); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 读取请求帧 |
|
|
|
* @details |
|
|
|
* |
|
|
|
* @param[out] *requestFrame 接收请求数据帧结构体地址 |
|
|
|
* @param[in] timeOut 读取请求帧数据超时时间 |
|
|
|
* |
|
|
|
* @return RESUIL 读取结果 |
|
|
|
* @retval MODBUS_TURE 成功 |
|
|
|
* @retval MODBUS_FALSE 失败 |
|
|
|
*/ |
|
|
|
RESUIL OperateAckFrameRead(ACK_FRAME *ackFrame, OS_TICK timeOut) |
|
|
|
{ |
|
|
|
OS_ERR err; |
|
|
|
OS_MSG_SIZE msgSize; |
|
|
|
void *pMsgAddr = NULL; |
|
|
|
|
|
|
|
pMsgAddr = OSQPend(&AckQueue, |
|
|
|
timeOut, |
|
|
|
OS_OPT_PEND_BLOCKING, |
|
|
|
&msgSize, |
|
|
|
0, |
|
|
|
&err); |
|
|
|
|
|
|
|
if (err == OS_ERR_NONE) |
|
|
|
{ |
|
|
|
memcpy(ackFrame, pMsgAddr, sizeof(ACK_FRAME)); |
|
|
|
return MODBUS_TURE; |
|
|
|
} |
|
|
|
else |
|
|
|
return MODBUS_FALSE; |
|
|
|
} |