summaryrefslogtreecommitdiff
path: root/components/net
diff options
context:
space:
mode:
author陈豪 | Jacob Chen <[email protected]>2015-03-29 18:35:44 +0800
committer陈豪 | Jacob Chen <[email protected]>2015-03-29 18:35:44 +0800
commit9a4dacaad743801c9be2dbae49251c4e1b8f99a9 (patch)
tree34def3bef5c5fc4a9b7594eba5a2729f8c86aab0 /components/net
parentdaac5388afe5a18d51e9839719de8423b62b00c1 (diff)
parent5af7abd8c2e8b8a39c0bf096bdf9b5cb08f266fa (diff)
Merge pull request #3 from RT-Thread/master
111
Diffstat (limited to 'components/net')
-rw-r--r--components/net/freemodbus-v1.6.0/port/portserial.c189
-rw-r--r--components/net/freemodbus-v1.6.0/port/portserial_m.c192
-rw-r--r--components/net/freemodbus-v1.6.0/port/porttimer.c107
-rw-r--r--components/net/freemodbus-v1.6.0/port/porttimer_m.c157
-rw-r--r--components/net/freemodbus-v1.6.0/port/user_mb_app.c349
-rw-r--r--components/net/freemodbus-v1.6.0/port/user_mb_app.h54
-rw-r--r--components/net/freemodbus/Changelog.txt (renamed from components/net/freemodbus-v1.6.0/Changelog.txt)0
-rw-r--r--components/net/freemodbus/SConscript (renamed from components/net/freemodbus-v1.6.0/SConscript)5
-rw-r--r--components/net/freemodbus/bsd.txt (renamed from components/net/freemodbus-v1.6.0/bsd.txt)0
-rw-r--r--components/net/freemodbus/gpl.txt (renamed from components/net/freemodbus-v1.6.0/gpl.txt)0
-rw-r--r--components/net/freemodbus/lgpl.txt (renamed from components/net/freemodbus-v1.6.0/lgpl.txt)0
-rw-r--r--components/net/freemodbus/modbus/ascii/mbascii.c (renamed from components/net/freemodbus-v1.6.0/modbus/ascii/mbascii.c)0
-rw-r--r--components/net/freemodbus/modbus/ascii/mbascii.h (renamed from components/net/freemodbus-v1.6.0/modbus/ascii/mbascii.h)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbfunccoils.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils.c)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbfunccoils_m.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c)73
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncdiag.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdiag.c)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncdisc.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc.c)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncdisc_m.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c)28
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncholding.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding.c)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncholding_m.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c)101
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncinput.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput.c)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncinput_m.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c)28
-rw-r--r--components/net/freemodbus/modbus/functions/mbfuncother.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbfuncother.c)0
-rw-r--r--components/net/freemodbus/modbus/functions/mbutils.c (renamed from components/net/freemodbus-v1.6.0/modbus/functions/mbutils.c)0
-rw-r--r--components/net/freemodbus/modbus/include/mb.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mb.h)0
-rw-r--r--components/net/freemodbus/modbus/include/mb_m.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mb_m.h)180
-rw-r--r--components/net/freemodbus/modbus/include/mbconfig.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h)6
-rw-r--r--components/net/freemodbus/modbus/include/mbframe.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mbframe.h)0
-rw-r--r--components/net/freemodbus/modbus/include/mbfunc.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mbfunc.h)0
-rw-r--r--components/net/freemodbus/modbus/include/mbport.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mbport.h)50
-rw-r--r--components/net/freemodbus/modbus/include/mbproto.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mbproto.h)0
-rw-r--r--components/net/freemodbus/modbus/include/mbutils.h (renamed from components/net/freemodbus-v1.6.0/modbus/include/mbutils.h)0
-rw-r--r--components/net/freemodbus/modbus/mb.c (renamed from components/net/freemodbus-v1.6.0/modbus/mb.c)0
-rw-r--r--components/net/freemodbus/modbus/mb_m.c (renamed from components/net/freemodbus-v1.6.0/modbus/mb_m.c)114
-rw-r--r--components/net/freemodbus/modbus/rtu/mbcrc.c (renamed from components/net/freemodbus-v1.6.0/modbus/rtu/mbcrc.c)0
-rw-r--r--components/net/freemodbus/modbus/rtu/mbcrc.h (renamed from components/net/freemodbus-v1.6.0/modbus/rtu/mbcrc.h)0
-rw-r--r--components/net/freemodbus/modbus/rtu/mbrtu.c (renamed from components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu.c)0
-rw-r--r--components/net/freemodbus/modbus/rtu/mbrtu.h (renamed from components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu.h)0
-rw-r--r--components/net/freemodbus/modbus/rtu/mbrtu_m.c (renamed from components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c)36
-rw-r--r--components/net/freemodbus/modbus/tcp/mbtcp.c (renamed from components/net/freemodbus-v1.6.0/modbus/tcp/mbtcp.c)0
-rw-r--r--components/net/freemodbus/modbus/tcp/mbtcp.h (renamed from components/net/freemodbus-v1.6.0/modbus/tcp/mbtcp.h)0
-rw-r--r--components/net/freemodbus/port/port.c (renamed from components/net/freemodbus-v1.6.0/port/port.c)15
-rw-r--r--components/net/freemodbus/port/port.h (renamed from components/net/freemodbus-v1.6.0/port/port.h)20
-rw-r--r--components/net/freemodbus/port/portevent.c (renamed from components/net/freemodbus-v1.6.0/port/portevent.c)38
-rw-r--r--components/net/freemodbus/port/portevent_m.c239
-rw-r--r--components/net/freemodbus/port/portserial.c222
-rw-r--r--components/net/freemodbus/port/portserial_m.c225
-rw-r--r--components/net/freemodbus/port/porttimer.c (renamed from components/net/freemodbus-v1.6.0/port/portevent_m.c)52
-rw-r--r--components/net/freemodbus/port/porttimer_m.c107
-rw-r--r--components/net/freemodbus/port/user_mb_app.c286
-rw-r--r--components/net/freemodbus/port/user_mb_app.h46
-rw-r--r--components/net/freemodbus/port/user_mb_app_m.c294
-rw-r--r--components/net/lwip-1.4.1/src/core/ipv4/ip.c37
-rw-r--r--components/net/lwip-1.4.1/src/lwipopts.h6
-rw-r--r--components/net/lwip_dhcpd/SConscript10
-rw-r--r--components/net/lwip_dhcpd/dhcp_server.c398
-rw-r--r--components/net/lwip_dhcpd/dhcp_server.h36
-rw-r--r--components/net/lwip_nat/README.md19
-rw-r--r--components/net/lwip_nat/SConscript10
-rw-r--r--components/net/lwip_nat/ipv4_nat.c1154
-rw-r--r--components/net/lwip_nat/ipv4_nat.h103
61 files changed, 3748 insertions, 1238 deletions
diff --git a/components/net/freemodbus-v1.6.0/port/portserial.c b/components/net/freemodbus-v1.6.0/port/portserial.c
deleted file mode 100644
index 3768702087..0000000000
--- a/components/net/freemodbus-v1.6.0/port/portserial.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * FreeModbus Libary: STM32 Port
- * Copyright (C) 2013 Armink <[email protected]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $
- */
-
-#include "port.h"
-
-/* ----------------------- Modbus includes ----------------------------------*/
-#include "mb.h"
-#include "mbport.h"
-/* ----------------------- static functions ---------------------------------*/
-static void prvvUARTTxReadyISR(void);
-static void prvvUARTRxISR(void);
-/* ----------------------- Start implementation -----------------------------*/
-
-void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
-{
- if (xRxEnable)
- {
- SLAVE_RS485_RECEIVE_MODE;
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
- }
- else
- {
- SLAVE_RS485_SEND_MODE;
- USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
- }
- if (xTxEnable)
- {
- USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
- }
- else
- {
- USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
- }
-}
-
-void vMBPortClose(void)
-{
- USART_ITConfig(USART1, USART_IT_TXE | USART_IT_RXNE, DISABLE);
- USART_Cmd(USART1, DISABLE);
-}
-//Ĭ��һ���ӻ� ����1 �����ʿ����� ��ż���������
-BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
- eMBParity eParity)
-{
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- //======================ʱ�ӳ�ʼ��=======================================
- RCC_APB2PeriphClockCmd(
- RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1,
- ENABLE);
- //======================IO��ʼ��=======================================
- //USART1_TX
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- //USART1_RX
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- //����485���ͺͽ���ģʽ
-// TODO ��ʱ��дB13 ��֮����������ʱ���޸�
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- //======================���ڳ�ʼ��=======================================
- USART_InitStructure.USART_BaudRate = ulBaudRate;
- //����У��ģʽ
- switch (eParity)
- {
- case MB_PAR_NONE: //����
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- break;
- case MB_PAR_ODD: //����
- USART_InitStructure.USART_Parity = USART_Parity_Odd;
- USART_InitStructure.USART_WordLength = USART_WordLength_9b;
- break;
- case MB_PAR_EVEN: //żУ��
- USART_InitStructure.USART_Parity = USART_Parity_Even;
- USART_InitStructure.USART_WordLength = USART_WordLength_9b;
- break;
- default:
- return FALSE;
- }
-
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_HardwareFlowControl =
- USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- if (ucPORT != 1)
- return FALSE;
-
- ENTER_CRITICAL_SECTION(); //��ȫ���ж�
-
- USART_Init(USART1, &USART_InitStructure);
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
- USART_Cmd(USART1, ENABLE);
-
- //=====================�жϳ�ʼ��======================================
- //����NVIC���ȼ�����ΪGroup2��0-3��ռʽ���ȼ���0-3����Ӧʽ���ȼ�
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
- EXIT_CRITICAL_SECTION(); //��ȫ���ж�
-
- return TRUE;
-}
-
-BOOL xMBPortSerialPutByte(CHAR ucByte)
-{
- USART_SendData(USART1, ucByte);
- return TRUE;
-}
-
-BOOL xMBPortSerialGetByte(CHAR * pucByte)
-{
- *pucByte = USART_ReceiveData(USART1);
- return TRUE;
-}
-
-/*
- * Create an interrupt handler for the transmit buffer empty interrupt
- * (or an equivalent) for your target processor. This function should then
- * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
- * a new character can be sent. The protocol stack will then call
- * xMBPortSerialPutByte( ) to send the character.
- */
-void prvvUARTTxReadyISR(void)
-{
- pxMBFrameCBTransmitterEmpty();
-}
-
-/*
- * Create an interrupt handler for the receive interrupt for your target
- * processor. This function should then call pxMBFrameCBByteReceived( ). The
- * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
- * character.
- */
-void prvvUARTRxISR(void)
-{
- pxMBFrameCBByteReceived();
-}
-/*******************************************************************************
- * Function Name : USART1_IRQHandler
- * Description : This function handles USART1 global interrupt request.
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
-void USART1_IRQHandler(void)
-{
- rt_interrupt_enter();
- //�����ж�
- if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
- {
- USART_ClearITPendingBit(USART1, USART_IT_RXNE);
- prvvUARTRxISR();
- }
- //�����ж�
- if (USART_GetITStatus(USART1, USART_IT_TXE) == SET)
- {
- prvvUARTTxReadyISR();
- }
- rt_interrupt_leave();
-}
diff --git a/components/net/freemodbus-v1.6.0/port/portserial_m.c b/components/net/freemodbus-v1.6.0/port/portserial_m.c
deleted file mode 100644
index ca76a81963..0000000000
--- a/components/net/freemodbus-v1.6.0/port/portserial_m.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * FreeModbus Libary: STM32 Port
- * Copyright (C) 2013 Armink <[email protected]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * File: $Id: portserial_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $
- */
-
-#include "port.h"
-
-/* ----------------------- Modbus includes ----------------------------------*/
-#include "mb.h"
-#include "mbport.h"
-
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
-/* ----------------------- static functions ---------------------------------*/
-static void prvvUARTTxReadyISR(void);
-static void prvvUARTRxISR(void);
-/* ----------------------- Start implementation -----------------------------*/
-
-void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
-{
- if (xRxEnable)
- {
- MASTER_RS485_RECEIVE_MODE;
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
- }
- else
- {
- MASTER_RS485_SEND_MODE;
- USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
- }
- if (xTxEnable)
- {
- USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
- }
- else
- {
- USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
- }
-}
-
-void vMBMasterPortClose(void)
-{
- USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE);
- USART_Cmd(USART2, DISABLE);
-}
-//Ĭ��һ������ ����2 �����ʿ����� ��ż���������
-BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
- eMBParity eParity)
-{
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- //======================ʱ�ӳ�ʼ��=======================================
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- //======================IO��ʼ��=======================================
- //USART2_TX
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- //USART2_RX
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- //����485���ͺͽ���ģʽ
-// TODO ��ʱ��дB13 ��֮����������ʱ���޸�
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- //======================���ڳ�ʼ��=======================================
- USART_InitStructure.USART_BaudRate = ulBaudRate;
- //����У��ģʽ
- switch (eParity)
- {
- case MB_PAR_NONE: //����
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- break;
- case MB_PAR_ODD: //����
- USART_InitStructure.USART_Parity = USART_Parity_Odd;
- USART_InitStructure.USART_WordLength = USART_WordLength_9b;
- break;
- case MB_PAR_EVEN: //żУ��
- USART_InitStructure.USART_Parity = USART_Parity_Even;
- USART_InitStructure.USART_WordLength = USART_WordLength_9b;
- break;
- default:
- return FALSE;
- }
-
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_HardwareFlowControl =
- USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- if (ucPORT != 2)
- return FALSE;
-
- ENTER_CRITICAL_SECTION(); //��ȫ���ж�
-
- USART_Init(USART2, &USART_InitStructure);
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
- USART_Cmd(USART2, ENABLE);
-
- //=====================�жϳ�ʼ��======================================
- //����NVIC���ȼ�����ΪGroup2��0-3��ռʽ���ȼ���0-3����Ӧʽ���ȼ�
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
- EXIT_CRITICAL_SECTION(); //��ȫ���ж�
-
- return TRUE;
-}
-
-BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
-{
- USART_SendData(USART2, ucByte);
- return TRUE;
-}
-
-BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
-{
- *pucByte = USART_ReceiveData(USART2);
- return TRUE;
-}
-
-/*
- * Create an interrupt handler for the transmit buffer empty interrupt
- * (or an equivalent) for your target processor. This function should then
- * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
- * a new character can be sent. The protocol stack will then call
- * xMBPortSerialPutByte( ) to send the character.
- */
-void prvvUARTTxReadyISR(void)
-{
- pxMBMasterFrameCBTransmitterEmpty();
-}
-
-/*
- * Create an interrupt handler for the receive interrupt for your target
- * processor. This function should then call pxMBFrameCBByteReceived( ). The
- * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
- * character.
- */
-void prvvUARTRxISR(void)
-{
- pxMBMasterFrameCBByteReceived();
-}
-/*******************************************************************************
- * Function Name : USART2_IRQHandler
- * Description : This function handles USART2 global interrupt request.
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
-void USART2_IRQHandler(void)
-{
- rt_interrupt_enter();
- //�����ж�
- if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
- {
- USART_ClearITPendingBit(USART2, USART_IT_RXNE);
- prvvUARTRxISR();
- }
- //�����ж�
- if (USART_GetITStatus(USART2, USART_IT_TXE) == SET)
- {
- prvvUARTTxReadyISR();
- }
- rt_interrupt_leave();
-}
-
-#endif
diff --git a/components/net/freemodbus-v1.6.0/port/porttimer.c b/components/net/freemodbus-v1.6.0/port/porttimer.c
deleted file mode 100644
index b7b74ce078..0000000000
--- a/components/net/freemodbus-v1.6.0/port/porttimer.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * FreeModbus Libary: STM32 Port
- * Copyright (C) 2013 Armink <[email protected]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * File: $Id: porttimer.c,v 1.60 2013/08/13 15:07:05 Armink $
- */
-
-/* ----------------------- Platform includes --------------------------------*/
-#include "port.h"
-
-/* ----------------------- Modbus includes ----------------------------------*/
-#include "mb.h"
-#include "mbport.h"
-
-/* ----------------------- static functions ---------------------------------*/
-static void prvvTIMERExpiredISR(void);
-
-/* ----------------------- Start implementation -----------------------------*/
-BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
-{
-
- uint16_t PrescalerValue = 0;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- //====================================ʱ�ӳ�ʼ��===========================
- //ʹ�ܶ�ʱ��3ʱ��
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
- //====================================��ʱ����ʼ��===========================
- //��ʱ��ʱ�������˵��
- //HCLKΪ72MHz��APB1����2��ƵΪ36MHz
- //TIM3��ʱ�ӱ�Ƶ��Ϊ72MHz��Ӳ���Զ���Ƶ,�ﵽ���
- //TIM3�ķ�Ƶϵ��Ϊ3599��ʱ���Ƶ��Ϊ72 / (1 + Prescaler) = 20KHz,��׼Ϊ50us
- //TIM������ֵΪusTim1Timerout50u
-
- PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
- //��ʱ��1��ʼ��
- TIM_TimeBaseStructure.TIM_Period = (uint16_t) usTim1Timerout50us;
- TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
- //Ԥװ��ʹ��
- TIM_ARRPreloadConfig(TIM3, ENABLE);
- //====================================�жϳ�ʼ��===========================
- //����NVIC���ȼ�����ΪGroup2��0-3��ռʽ���ȼ���0-3����Ӧʽ���ȼ�
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- //�������жϱ�־λ
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- //��ʱ��3����жϹر�
- TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
- //��ʱ��3����
- TIM_Cmd(TIM3, DISABLE);
- return TRUE;
-}
-
-void vMBPortTimersEnable()
-{
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
- TIM_SetCounter(TIM3, 0);
- TIM_Cmd(TIM3, ENABLE);
-}
-
-void vMBPortTimersDisable()
-{
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
- TIM_SetCounter(TIM3, 0);
- TIM_Cmd(TIM3, DISABLE);
-}
-
-void prvvTIMERExpiredISR(void)
-{
- (void) pxMBPortCBTimerExpired();
-}
-
-void TIM3_IRQHandler(void)
-{
- rt_interrupt_enter();
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
- {
-
- TIM_ClearFlag(TIM3, TIM_FLAG_Update); //���жϱ��
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //�����ʱ��T3����жϱ�־λ
- prvvTIMERExpiredISR();
- }
- rt_interrupt_leave();
-}
diff --git a/components/net/freemodbus-v1.6.0/port/porttimer_m.c b/components/net/freemodbus-v1.6.0/port/porttimer_m.c
deleted file mode 100644
index 1881b47053..0000000000
--- a/components/net/freemodbus-v1.6.0/port/porttimer_m.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * FreeModbus Libary: STM32 Port
- * Copyright (C) 2013 Armink <[email protected]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * File: $Id: porttimer_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$
- */
-
-/* ----------------------- Platform includes --------------------------------*/
-#include "port.h"
-
-/* ----------------------- Modbus includes ----------------------------------*/
-#include "mb.h"
-#include "mb_m.h"
-#include "mbport.h"
-
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
-/* ----------------------- Variables ----------------------------------------*/
-static USHORT usT35TimeOut50us;
-static USHORT usPrescalerValue = 0;
-
-/* ----------------------- static functions ---------------------------------*/
-static void prvvTIMERExpiredISR(void);
-
-/* ----------------------- Start implementation -----------------------------*/
-BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
-{
- NVIC_InitTypeDef NVIC_InitStructure;
- //====================================ʱ�ӳ�ʼ��===========================
- //ʹ�ܶ�ʱ��2ʱ��
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
- //====================================��ʱ����ʼ��===========================
- //��ʱ��ʱ�������˵��
- //HCLKΪ72MHz��APB1����2��ƵΪ36MHz
- //TIM2��ʱ�ӱ�Ƶ��Ϊ72MHz��Ӳ���Զ���Ƶ,�ﵽ���
- //TIM2�ķ�Ƶϵ��Ϊ3599��ʱ���Ƶ��Ϊ72 / (1 + Prescaler) = 20KHz,��׼Ϊ50us
- //TIM������ֵΪusTim1Timerout50u
- usPrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
- //����T35��ʱ������ֵ
- usT35TimeOut50us = usTimeOut50us;
-
- //Ԥװ��ʹ��
- TIM_ARRPreloadConfig(TIM2, ENABLE);
- //====================================�жϳ�ʼ��===========================
- //����NVIC���ȼ�����ΪGroup2��0-3��ռʽ���ȼ���0-3����Ӧʽ���ȼ�
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- //�������жϱ�־λ
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- //��ʱ��3����жϹر�
- TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
- //��ʱ��3����
- TIM_Cmd(TIM2, DISABLE);
- return TRUE;
-}
-
-void vMBMasterPortTimersT35Enable()
-{
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
- /* Set current timer mode,don't change it.*/
- vMBMasterSetCurTimerMode(MB_TMODE_T35);
-
- TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_Period = (uint16_t) usT35TimeOut50us;
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
- TIM_SetCounter(TIM2, 0);
- TIM_Cmd(TIM2, ENABLE);
-}
-
-void vMBMasterPortTimersConvertDelayEnable()
-{
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
- /* Set current timer mode,don't change it.*/
- vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
-
- TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_DELAY_MS_CONVERT * 1000 / 50);
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
- TIM_SetCounter(TIM2, 0);
- TIM_Cmd(TIM2, ENABLE);
-}
-
-void vMBMasterPortTimersRespondTimeoutEnable()
-{
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
- /* Set current timer mode,don't change it.*/
- vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
-
- TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_TIMEOUT_MS_RESPOND * 1000 / 50);
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
- TIM_SetCounter(TIM2, 0);
- TIM_Cmd(TIM2, ENABLE);
-}
-
-void vMBMasterPortTimersDisable()
-{
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
- TIM_SetCounter(TIM2, 0);
- TIM_Cmd(TIM2, DISABLE);
-}
-
-void prvvTIMERExpiredISR(void)
-{
- (void) pxMBMasterPortCBTimerExpired();
-}
-
-void TIM2_IRQHandler(void)
-{
- rt_interrupt_enter();
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
- {
-
- TIM_ClearFlag(TIM2, TIM_FLAG_Update); //���жϱ��
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //�����ʱ��TIM2����жϱ�־λ
- prvvTIMERExpiredISR();
- }
- rt_interrupt_leave();
-}
-
-#endif
diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app.c b/components/net/freemodbus-v1.6.0/port/user_mb_app.c
deleted file mode 100644
index a99615c235..0000000000
--- a/components/net/freemodbus-v1.6.0/port/user_mb_app.c
+++ /dev/null
@@ -1,349 +0,0 @@
-#include "user_mb_app.h"
-/*------------------------Slave mode use these variables----------------------*/
-//Slave mode:DiscreteInputs variables
-USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
-#if S_DISCRETE_INPUT_NDISCRETES%8
-UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1];
-#else
-UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ;
-#endif
-//Slave mode:Coils variables
-USHORT usSCoilStart = S_COIL_START;
-#if S_COIL_NCOILS%8
-UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ;
-#else
-UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ;
-#endif
-//Slave mode:InputRegister variables
-USHORT usSRegInStart = S_REG_INPUT_START;
-USHORT usSRegInBuf[S_REG_INPUT_NREGS] ;
-//Slave mode:HoldingRegister variables
-USHORT usSRegHoldStart = S_REG_HOLDING_START;
-USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ;
-/*-----------------------Master mode use these variables----------------------*/
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
-//Master mode:DiscreteInputs variables
-USHORT usMDiscInStart = M_DISCRETE_INPUT_START;
-#if M_DISCRETE_INPUT_NDISCRETES%8
-UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
-#else
-UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
-#endif
-//Master mode:Coils variables
-USHORT usMCoilStart = M_COIL_START;
-#if M_COIL_NCOILS%8
-UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
-#else
-UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
-#endif
-//Master mode:InputRegister variables
-USHORT usMRegInStart = M_REG_INPUT_START;
-USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
-//Master mode:HoldingRegister variables
-USHORT usMRegHoldStart = M_REG_HOLDING_START;
-USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
-#endif
-//******************************����Ĵ����ص�����**********************************
-//��������: eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
-//�� ��������Ĵ�����صĹ��ܣ�������������
-//��ڲ�����pucRegBuffer : �ص�������Modbus�Ĵ����ĵ�ǰֵд��Ļ�����
-// usAddress : �Ĵ�������ʼ��ַ������Ĵ����ĵ�ַ��Χ��1-65535��
-// usNRegs : �Ĵ�������
-//���ڲ�����eMBErrorCode : ������������صĴ�����
-//�� ע��Editor��Armink 2010-10-31 Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
-{
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- USHORT * pusRegInputBuf;
- UCHAR REG_INPUT_START;
- UCHAR REG_INPUT_NREGS;
- UCHAR usRegInStart;
-
- //Determine the master or slave
- if (xMBMasterGetCBRunInMasterMode())
- {
- pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress()];
- REG_INPUT_START = M_REG_INPUT_START;
- REG_INPUT_NREGS = M_REG_INPUT_NREGS;
- usRegInStart = usMRegInStart;
- }
- else
- {
- pusRegInputBuf = usSRegInBuf;
- REG_INPUT_START = S_REG_INPUT_START;
- REG_INPUT_NREGS = S_REG_INPUT_NREGS;
- usRegInStart = usSRegInStart;
- }
-
- if( ( usAddress >= REG_INPUT_START )
- && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
- {
- iRegIndex = ( int )( usAddress - usRegInStart );
- while( usNRegs > 0 )
- {
- //Determine the master or slave
- if (xMBMasterGetCBRunInMasterMode())
- {
- pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
- pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
- }
- else
- {
- *pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] & 0xFF );
- }
- iRegIndex++;
- usNRegs--;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
-
- return eStatus;
-}
-//******************************���ּĴ����ص�����**********************************
-//��������: eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
-//�� �������ּĴ�����صĹ��ܣ�������������д������д��
-//��ڲ�����pucRegBuffer : �����Ҫ�����û��Ĵ�����ֵ���������������ָ���µļĴ�����ֵ��
-// ���Э��ջ��֪����ǰ����ֵ���ص��������뽫��ǰֵд�����������
-// usAddress : �Ĵ�������ʼ��ַ��
-// usNRegs : �Ĵ�������
-// eMode : ����ò���ΪeMBRegisterMode::MB_REG_WRITE���û���Ӧ����ֵ����pucRegBuffer�еõ����¡�
-// ����ò���ΪeMBRegisterMode::MB_REG_READ���û���Ҫ����ǰ��Ӧ�����ݴ洢��pucRegBuffer��
-//���ڲ�����eMBErrorCode : ������������صĴ�����
-//�� ע��Editor��Armink 2010-10-31 Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
-{
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- USHORT * pusRegHoldingBuf;
- UCHAR REG_HOLDING_START;
- UCHAR REG_HOLDING_NREGS;
- UCHAR usRegHoldStart;
-
- //Determine the master or slave
- if (xMBMasterGetCBRunInMasterMode())
- {
- pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress()];
- REG_HOLDING_START = M_REG_HOLDING_START;
- REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
- usRegHoldStart = usMRegHoldStart;
- //If mode is read,the master will wirte the received date to bufffer.
- eMode = MB_REG_WRITE;
- }
- else
- {
- pusRegHoldingBuf = usSRegHoldBuf;
- REG_HOLDING_START = S_REG_HOLDING_START;
- REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
- usRegHoldStart = usSRegHoldStart;
- }
-
- if( ( usAddress >= REG_HOLDING_START ) &&
- ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
- {
- iRegIndex = ( int )( usAddress - usRegHoldStart );
- switch ( eMode )
- {
- /* Pass current register values to the protocol stack. */
- case MB_REG_READ:
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- break;
-
- /* Update current register values with new values from the
- * protocol stack. */
- case MB_REG_WRITE:
- while( usNRegs > 0 )
- {
- pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- break;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
-}
-//****************************��Ȧ״̬�Ĵ����ص�����********************************
-//��������: eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
-//�� ������Ȧ״̬�Ĵ�����صĹ��ܣ�������������д������д��
-//��ڲ�����pucRegBuffer : λ���һ���ֽڣ���ʼ�Ĵ�����Ӧ��λ���ڸ��ֽ�pucRegBuffer�����λLSB��
-// ����ص�����Ҫд�����������û���õ�����Ȧ�����粻��8��һ�����Ȧ״̬����Ӧ��λ����ֵ��������λ0��
-// usAddress : ��һ����Ȧ��ַ��
-// usNCoils : �������Ȧ����
-// eMode ������ò���ΪeMBRegisterMode::MB_REG_WRITE���û���Ӧ����ֵ����pucRegBuffer�еõ����¡�
-// ����ò���ΪeMBRegisterMode::MB_REG_READ���û���Ҫ����ǰ��Ӧ�����ݴ洢��pucRegBuffer��
-//���ڲ�����eMBErrorCode : ������������صĴ�����
-//�� ע��Editor��Armink 2010-10-31 Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
-{
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex , iRegBitIndex , iNReg;
- UCHAR * pucCoilBuf;
- UCHAR COIL_START;
- UCHAR COIL_NCOILS;
- UCHAR usCoilStart;
- iNReg = usNCoils / 8 + 1; //ռ�üĴ�������
-
-
- //Determine the master or slave
- if (xMBMasterGetCBRunInMasterMode())
- {
- pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress()];
- COIL_START = M_COIL_START;
- COIL_NCOILS = M_COIL_NCOILS;
- usCoilStart = usMCoilStart;
- //If mode is read,the master will wirte the received date to bufffer.
- eMode = MB_REG_WRITE;
- }
- else
- {
- pucCoilBuf = ucSCoilBuf;
- COIL_START = S_COIL_START;
- COIL_NCOILS = S_COIL_NCOILS;
- usCoilStart = usSCoilStart;
- }
-
- if( ( usAddress >= COIL_START ) &&
- ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
- {
- iRegIndex = ( int )( usAddress - usCoilStart ) / 8 ; //ÿ���Ĵ�����8��
- iRegBitIndex = ( int )( usAddress - usCoilStart ) % 8 ; //����ڼĴ����ڲ���λ��ַ
- switch ( eMode )
- {
- /* Pass current coil values to the protocol stack. */
- case MB_REG_READ:
- while( iNReg > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8);
- iNReg --;
- }
- pucRegBuffer --;
- usNCoils = usNCoils % 8; //���µ���Ȧ��
- *pucRegBuffer = *pucRegBuffer <<(8 - usNCoils); //�����
- *pucRegBuffer = *pucRegBuffer >>(8 - usNCoils);
- break;
-
- /* Update current coil values with new values from the
- * protocol stack. */
- case MB_REG_WRITE:
- while(iNReg > 1) //���������������������
- {
- xMBUtilSetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++);
- iNReg--;
- }
- usNCoils = usNCoils % 8; //���µ���Ȧ��
- if (usNCoils != 0) //xMBUtilSetBits���� �ڲ���λ����Ϊ0ʱ����bug
- {
- xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
- *pucRegBuffer++);
- }
- break;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
-}
-//****************************��ɢ����Ĵ����ص�����********************************
-//��������: eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
-//�� ������ɢ����Ĵ�����صĹ��ܣ�������������
-//��ڲ�����pucRegBuffer : �õ�ǰ����Ȧ���ݸ�������Ĵ�������ʼ�Ĵ�����Ӧ��λ���ڸ��ֽ�pucRegBuffer�����λLSB��
-// ����ص�����Ҫд�����������û���õ�����Ȧ�����粻��8��һ�����Ȧ״̬����Ӧ��λ����ֵ��������Ϊ0��
-// usAddress : ��ɢ�������ʼ��ַ
-// usNDiscrete : ��ɢ���������
-//���ڲ�����eMBErrorCode : ������������صĴ�����
-//�� ע��Editor��Armink 2010-10-31 Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
-{
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex , iRegBitIndex , iNReg;
- UCHAR * pucDiscreteInputBuf;
- UCHAR DISCRETE_INPUT_START;
- UCHAR DISCRETE_INPUT_NDISCRETES;
- UCHAR usDiscreteInputStart;
- iNReg = usNDiscrete / 8 + 1; //ռ�üĴ�������
-
- //Determine the master or slave
- if (xMBMasterGetCBRunInMasterMode())
- {
- pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress()];
- DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
- DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
- usDiscreteInputStart = usMDiscInStart;
- }
- else
- {
- pucDiscreteInputBuf = ucSDiscInBuf;
- DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
- DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
- usDiscreteInputStart = usSDiscInStart;
- }
-
- if( ( usAddress >= DISCRETE_INPUT_START )
- && ( usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES ) )
- {
- iRegIndex = ( int )( usAddress - usDiscreteInputStart ) / 8 ; //ÿ���Ĵ�����8��
- iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ; //����ڼĴ����ڲ���λ��ַ
-
- //Determine the master or slave
- if (xMBMasterGetCBRunInMasterMode())
- {
- /* Update current coil values with new values from the
- * protocol stack. */
- while(iNReg > 1) //���������������������
- {
- xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++);
- iNReg--;
- }
- usNDiscrete = usNDiscrete % 8; //���µ���Ȧ��
- if (usNDiscrete != 0) //xMBUtilSetBits���� �ڲ���λ����Ϊ0ʱ����bug
- {
- xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
- usNDiscrete, *pucRegBuffer++);
- }
- }
- else
- {
- while( iNReg > 0 )
- {
- *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8);
- iNReg --;
- }
- pucRegBuffer --;
- usNDiscrete = usNDiscrete % 8; //���µ���Ȧ��
- *pucRegBuffer = *pucRegBuffer <<(8 - usNDiscrete); //�����
- *pucRegBuffer = *pucRegBuffer >>(8 - usNDiscrete);
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
-
- return eStatus;
-}
diff --git a/components/net/freemodbus-v1.6.0/port/user_mb_app.h b/components/net/freemodbus-v1.6.0/port/user_mb_app.h
deleted file mode 100644
index 440ca82135..0000000000
--- a/components/net/freemodbus-v1.6.0/port/user_mb_app.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef USER_APP
-#define USER_APP
-/* ----------------------- Modbus includes ----------------------------------*/
-#include "mb.h"
-#include "mb_m.h"
-#include "mbconfig.h"
-#include "mbframe.h"
-#include "mbutils.h"
-
-/* -----------------------Slave Defines -------------------------------------*/
-#define S_DISCRETE_INPUT_START 1
-#define S_DISCRETE_INPUT_NDISCRETES 16
-#define S_COIL_START 1
-#define S_COIL_NCOILS 64
-#define S_REG_INPUT_START 1
-#define S_REG_INPUT_NREGS 100
-#define S_REG_HOLDING_START 1
-#define S_REG_HOLDING_NREGS 100
-//�ӻ�ģʽ���ڱ��ּĴ����У�������ַ��Ӧ�Ĺ��ܶ���
-#define S_HD_RESERVE 0 //����
-#define S_HD_CPU_USAGE_MAJOR 1 //��ǰCPU�����ʵ�����λ
-#define S_HD_CPU_USAGE_MINOR 2 //��ǰCPU�����ʵ�С��λ
-
-//�ӻ�ģʽ��������Ĵ����У�������ַ��Ӧ�Ĺ��ܶ���
-#define S_IN_RESERVE 0 //����
-
-//�ӻ�ģʽ������Ȧ�У�������ַ��Ӧ�Ĺ��ܶ���
-#define S_CO_RESERVE 2 //����
-
-//�ӻ�ģʽ������ɢ�����У�������ַ��Ӧ�Ĺ��ܶ���
-#define S_DI_RESERVE 1 //����
-
-/* -----------------------Master Defines -------------------------------------*/
-#define M_DISCRETE_INPUT_START 1
-#define M_DISCRETE_INPUT_NDISCRETES 16
-#define M_COIL_START 1
-#define M_COIL_NCOILS 64
-#define M_REG_INPUT_START 1
-#define M_REG_INPUT_NREGS 100
-#define M_REG_HOLDING_START 1
-#define M_REG_HOLDING_NREGS 100
-//����ģʽ���ڱ��ּĴ����У�������ַ��Ӧ�Ĺ��ܶ���
-#define M_HD_RESERVE 0 //����
-
-//����ģʽ��������Ĵ����У�������ַ��Ӧ�Ĺ��ܶ���
-#define M_IN_RESERVE 0 //����
-
-//����ģʽ������Ȧ�У�������ַ��Ӧ�Ĺ��ܶ���
-#define M_CO_RESERVE 2 //����
-
-//����ģʽ������ɢ�����У�������ַ��Ӧ�Ĺ��ܶ���
-#define M_DI_RESERVE 1 //����
-
-#endif
diff --git a/components/net/freemodbus-v1.6.0/Changelog.txt b/components/net/freemodbus/Changelog.txt
index 2816ea30f3..2816ea30f3 100644
--- a/components/net/freemodbus-v1.6.0/Changelog.txt
+++ b/components/net/freemodbus/Changelog.txt
diff --git a/components/net/freemodbus-v1.6.0/SConscript b/components/net/freemodbus/SConscript
index 77ab37e086..d613a9f398 100644
--- a/components/net/freemodbus-v1.6.0/SConscript
+++ b/components/net/freemodbus/SConscript
@@ -7,7 +7,6 @@ modbus/functions/mbutils.c
modbus/functions/mbfuncother.c
modbus/rtu/mbcrc.c
port/port.c
-port/user_mb_app.c
""")
master_rtu_src = Split("""
@@ -20,6 +19,7 @@ modbus/mb_m.c
port/portevent_m.c
port/portserial_m.c
port/porttimer_m.c
+port/user_mb_app_m.c
""")
slave_rtu_src = Split("""
@@ -32,6 +32,7 @@ modbus/mb.c
port/portevent.c
port/portserial.c
port/porttimer.c
+port/user_mb_app.c
""")
master_slave_rtu_src = Split("""
@@ -53,6 +54,8 @@ port/portserial.c
port/portserial_m.c
port/porttimer.c
port/porttimer_m.c
+port/user_mb_app.c
+port/user_mb_app_m.c
""")
# The set of source files associated with this SConscript file.
diff --git a/components/net/freemodbus-v1.6.0/bsd.txt b/components/net/freemodbus/bsd.txt
index 362d3e37c8..362d3e37c8 100644
--- a/components/net/freemodbus-v1.6.0/bsd.txt
+++ b/components/net/freemodbus/bsd.txt
diff --git a/components/net/freemodbus-v1.6.0/gpl.txt b/components/net/freemodbus/gpl.txt
index 3912109b5c..3912109b5c 100644
--- a/components/net/freemodbus-v1.6.0/gpl.txt
+++ b/components/net/freemodbus/gpl.txt
diff --git a/components/net/freemodbus-v1.6.0/lgpl.txt b/components/net/freemodbus/lgpl.txt
index 8add30ad59..8add30ad59 100644
--- a/components/net/freemodbus-v1.6.0/lgpl.txt
+++ b/components/net/freemodbus/lgpl.txt
diff --git a/components/net/freemodbus-v1.6.0/modbus/ascii/mbascii.c b/components/net/freemodbus/modbus/ascii/mbascii.c
index b0f3bc05d2..b0f3bc05d2 100644
--- a/components/net/freemodbus-v1.6.0/modbus/ascii/mbascii.c
+++ b/components/net/freemodbus/modbus/ascii/mbascii.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/ascii/mbascii.h b/components/net/freemodbus/modbus/ascii/mbascii.h
index cdec83ff00..cdec83ff00 100644
--- a/components/net/freemodbus-v1.6.0/modbus/ascii/mbascii.h
+++ b/components/net/freemodbus/modbus/ascii/mbascii.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils.c b/components/net/freemodbus/modbus/functions/mbfunccoils.c
index 681bd50656..681bd50656 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils.c
+++ b/components/net/freemodbus/modbus/functions/mbfunccoils.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c b/components/net/freemodbus/modbus/functions/mbfunccoils_m.c
index 553f57b1b7..f6bb51cdf6 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c
+++ b/components/net/freemodbus/modbus/functions/mbfunccoils_m.c
@@ -74,14 +74,24 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_COILS_ENABLED > 0
+/**
+ * This function will request read coil.
+ *
+ * @param ucSndAddr salve address
+ * @param usCoilAddr coil start address
+ * @param usNCoils coil total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
-eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils )
+eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -93,6 +103,8 @@ eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils )
ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
+
}
return eErrStatus;
}
@@ -108,7 +120,12 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+ /* If this request is broadcast, and it's read mode. This request don't need execute. */
+ if ( xMBMasterRequestIsBroadcast() )
+ {
+ eStatus = MB_EX_NONE;
+ }
+ else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -136,7 +153,7 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) )
{
/* Make callback to fill the buffer. */
- eRegStatus = eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
+ eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
@@ -161,15 +178,27 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_WRITE_COIL_ENABLED > 0
+/**
+ * This function will request write one coil.
+ *
+ * @param ucSndAddr salve address
+ * @param usCoilAddr coil start address
+ * @param usCoilData data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ *
+ * @see eMBMasterReqWriteMultipleCoils
+ */
eMBMasterReqErrCode
-eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData )
+eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( usCoilAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( usCoilAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -181,6 +210,7 @@ eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData )
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -214,7 +244,7 @@ eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
ucBuf[0] = 0;
}
eRegStatus =
- eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
+ eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
@@ -240,18 +270,31 @@ eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
+/**
+ * This function will request write multiple coils.
+ *
+ * @param ucSndAddr salve address
+ * @param usCoilAddr coil start address
+ * @param usNCoils coil total number
+ * @param usCoilData data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ *
+ * @see eMBMasterReqWriteCoil
+ */
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
- USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer )
+ USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut)
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
UCHAR ucByteCount;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -277,6 +320,7 @@ eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -293,7 +337,8 @@ eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE )
+ /* If this request is broadcast, the *usLen is not need check. */
+ if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
@@ -318,7 +363,7 @@ eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) )
{
eRegStatus =
- eMBRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
+ eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
usRegAddress, usCoilCnt, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdiag.c b/components/net/freemodbus/modbus/functions/mbfuncdiag.c
index d75ffc0f72..d75ffc0f72 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdiag.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncdiag.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc.c b/components/net/freemodbus/modbus/functions/mbfuncdisc.c
index fb378441b9..fb378441b9 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncdisc.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c b/components/net/freemodbus/modbus/functions/mbfuncdisc_m.c
index 187872c2a6..6c8d6c4741 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncdisc_m.c
@@ -57,16 +57,26 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
-#if MB_FUNC_READ_COILS_ENABLED > 0
+#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
+/**
+ * This function will request read discrete inputs.
+ *
+ * @param ucSndAddr salve address
+ * @param usDiscreteAddr discrete start address
+ * @param usNDiscreteIn discrete total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
-eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn )
+eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -78,6 +88,7 @@ eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT u
ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -93,7 +104,12 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+ /* If this request is broadcast, and it's read mode. This request don't need execute. */
+ if ( xMBMasterRequestIsBroadcast() )
+ {
+ eStatus = MB_EX_NONE;
+ }
+ else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -120,7 +136,7 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF])
{
/* Make callback to fill the buffer. */
- eRegStatus = eMBRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
+ eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding.c b/components/net/freemodbus/modbus/functions/mbfuncholding.c
index e74a0624dc..e74a0624dc 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncholding.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c b/components/net/freemodbus/modbus/functions/mbfuncholding_m.c
index faefbbbb40..e1fe69e383 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncholding_m.c
@@ -86,14 +86,24 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_WRITE_HOLDING_ENABLED > 0
+/**
+ * This function will request write holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usRegData register data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
-eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData )
+eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -105,6 +115,7 @@ eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRe
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -123,7 +134,7 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
usRegAddress++;
/* Make callback to update the value. */
- eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
+ eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
@@ -143,16 +154,27 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
+/**
+ * This function will request write multiple holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usNRegs register total number
+ * @param pusDataBuffer data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
- USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer )
+ USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -171,6 +193,7 @@ eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -186,7 +209,8 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE )
+ /* If this request is broadcast, the *usLen is not need check. */
+ if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 );
@@ -202,7 +226,7 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
/* Make callback to update the register values. */
eRegStatus =
- eMBRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
+ eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
usRegAddress, usRegCount, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
@@ -227,14 +251,24 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_READ_HOLDING_ENABLED > 0
+/**
+ * This function will request read holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usNRegs register total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
-eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs )
+eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -246,6 +280,7 @@ eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRe
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -260,7 +295,12 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+ /* If this request is broadcast, and it's read mode. This request don't need execute. */
+ if ( xMBMasterRequestIsBroadcast() )
+ {
+ eStatus = MB_EX_NONE;
+ }
+ else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -268,7 +308,7 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
- usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
+ usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
@@ -276,7 +316,7 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
{
/* Make callback to fill the buffer. */
- eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
+ eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
@@ -300,17 +340,30 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
+/**
+ * This function will request read and write holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usReadRegAddr read register start address
+ * @param usNReadRegs read register total number
+ * @param pusDataBuffer data to be written
+ * @param usWriteRegAddr write register start address
+ * @param usNWriteRegs write register total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
- USHORT usWriteRegAddr, USHORT usNWriteRegs )
+ USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -333,6 +386,7 @@ eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -349,7 +403,12 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN)
+ /* If this request is broadcast, and it's read mode. This request don't need execute. */
+ if ( xMBMasterRequestIsBroadcast() )
+ {
+ eStatus = MB_EX_NONE;
+ }
+ else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U );
@@ -369,13 +428,13 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] )
{
/* Make callback to update the register values. */
- eRegStatus = eMBRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
+ eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
if( eRegStatus == MB_ENOERR )
{
/* Make the read callback. */
- eRegStatus = eMBRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
+ eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
usRegReadAddress, usRegReadCount, MB_REG_READ);
}
if( eRegStatus != MB_ENOERR )
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput.c b/components/net/freemodbus/modbus/functions/mbfuncinput.c
index cceedbafea..cceedbafea 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncinput.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c b/components/net/freemodbus/modbus/functions/mbfuncinput_m.c
index e5f362bbec..2127efef67 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncinput_m.c
@@ -59,14 +59,24 @@ eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_INPUT_ENABLED > 0
+/**
+ * This function will request read input register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usNRegs register total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
eMBMasterReqErrCode
-eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs )
+eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
- if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
- else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+ else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -78,6 +88,7 @@ eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+ eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
@@ -92,7 +103,12 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
- if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN)
+ /* If this request is broadcast, and it's read mode. This request don't need execute. */
+ if ( xMBMasterRequestIsBroadcast() )
+ {
+ eStatus = MB_EX_NONE;
+ }
+ else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -100,7 +116,7 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
- usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
+ usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
@@ -108,7 +124,7 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
{
/* Make callback to fill the buffer. */
- eRegStatus = eMBRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
+ eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncother.c b/components/net/freemodbus/modbus/functions/mbfuncother.c
index fcee972bf8..fcee972bf8 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncother.c
+++ b/components/net/freemodbus/modbus/functions/mbfuncother.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbutils.c b/components/net/freemodbus/modbus/functions/mbutils.c
index 4ffbd3e001..4ffbd3e001 100644
--- a/components/net/freemodbus-v1.6.0/modbus/functions/mbutils.c
+++ b/components/net/freemodbus/modbus/functions/mbutils.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mb.h b/components/net/freemodbus/modbus/include/mb.h
index 8d6be7b422..8d6be7b422 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mb.h
+++ b/components/net/freemodbus/modbus/include/mb.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h b/components/net/freemodbus/modbus/include/mb_m.h
index 9c4fa43e60..f6b25e2cf3 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h
+++ b/components/net/freemodbus/modbus/include/mb_m.h
@@ -77,13 +77,10 @@ typedef enum
MB_MRE_NO_ERR, /*!< no error. */
MB_MRE_NO_REG, /*!< illegal register address. */
MB_MRE_ILL_ARG, /*!< illegal argument. */
- MB_MRE_PORT_ERR, /*!< porting layer error. */
- MB_MRE_NO_RES, /*!< insufficient resources. */
- MB_MRE_IO, /*!< I/O error. */
- MB_MRE_ILL_STATE, /*!< protocol stack in illegal state. */
+ MB_MRE_REV_DATA, /*!< receive data error. */
MB_MRE_TIMEDOUT, /*!< timeout error occurred. */
MB_MRE_MASTER_BUSY, /*!< master is busy now. */
- MB_MRE_SLAVE_EXCE /*!< slave has exception. */
+ MB_MRE_EXE_FUN /*!< execute function error. */
} eMBMasterReqErrCode;
/*! \ingroup modbus
* \brief TimerMode is Master 3 kind of Timer modes.
@@ -189,31 +186,176 @@ eMBErrorCode eMBMasterDisable( void );
*/
eMBErrorCode eMBMasterPoll( void );
+/*! \ingroup modbus
+ * \brief Registers a callback handler for a given function code.
+ *
+ * This function registers a new callback handler for a given function code.
+ * The callback handler supplied is responsible for interpreting the Modbus PDU and
+ * the creation of an appropriate response. In case of an error it should return
+ * one of the possible Modbus exceptions which results in a Modbus exception frame
+ * sent by the protocol stack.
+ *
+ * \param ucFunctionCode The Modbus function code for which this handler should
+ * be registers. Valid function codes are in the range 1 to 127.
+ * \param pxHandler The function handler which should be called in case
+ * such a frame is received. If \c NULL a previously registered function handler
+ * for this function code is removed.
+ *
+ * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no
+ * more resources are available it returns eMBErrorCode::MB_ENORES. In this
+ * case the values in mbconfig.h should be adjusted. If the argument was not
+ * valid it returns eMBErrorCode::MB_EINVAL.
+ */
+eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
+ pxMBFunctionHandler pxHandler );
+
+/* ----------------------- Callback -----------------------------------------*/
+
+/*! \defgroup modbus_master registers Modbus Registers
+ * \code #include "mb_m.h" \endcode
+ * The protocol stack does not internally allocate any memory for the
+ * registers. This makes the protocol stack very small and also usable on
+ * low end targets. In addition the values don't have to be in the memory
+ * and could for example be stored in a flash.<br>
+ * Whenever the protocol stack requires a value it calls one of the callback
+ * function with the register address and the number of registers to read
+ * as an argument. The application should then read the actual register values
+ * (for example the ADC voltage) and should store the result in the supplied
+ * buffer.<br>
+ * If the protocol stack wants to update a register value because a write
+ * register function was received a buffer with the new register values is
+ * passed to the callback function. The function should then use these values
+ * to update the application register values.
+ */
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if the value of a <em>Input Register</em>
+ * is required by the protocol stack. The starting register address is given
+ * by \c usAddress and the last register is given by <tt>usAddress +
+ * usNRegs - 1</tt>.
+ *
+ * \param pucRegBuffer A buffer where the callback function should write
+ * the current value of the modbus registers to.
+ * \param usAddress The starting address of the register. Input registers
+ * are in the range 1 - 65535.
+ * \param usNRegs Number of registers the callback function must supply.
+ *
+ * \return The function must return one of the following error codes:
+ * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ * Modbus response is sent.
+ * - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ * within the requested address range. In this case a
+ * <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNRegs );
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if a <em>Holding Register</em> value is
+ * read or written by the protocol stack. The starting register address
+ * is given by \c usAddress and the last register is given by
+ * <tt>usAddress + usNRegs - 1</tt>.
+ *
+ * \param pucRegBuffer If the application registers values should be updated the
+ * buffer points to the new registers values. If the protocol stack needs
+ * to now the current values the callback function should write them into
+ * this buffer.
+ * \param usAddress The starting address of the register.
+ * \param usNRegs Number of registers to read or write.
+ * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register
+ * values should be updated from the values in the buffer. For example
+ * this would be the case when the Modbus master has issued an
+ * <b>WRITE SINGLE REGISTER</b> command.
+ * If the value eMBRegisterMode::MB_REG_READ the application should copy
+ * the current values into the buffer \c pucRegBuffer.
+ *
+ * \return The function must return one of the following error codes:
+ * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ * Modbus response is sent.
+ * - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ * within the requested address range. In this case a
+ * <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNRegs, eMBRegisterMode eMode );
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if a <em>Coil Register</em> value is
+ * read or written by the protocol stack. If you are going to use
+ * this function you might use the functions xMBUtilSetBits( ) and
+ * xMBUtilGetBits( ) for working with bitfields.
+ *
+ * \param pucRegBuffer The bits are packed in bytes where the first coil
+ * starting at address \c usAddress is stored in the LSB of the
+ * first byte in the buffer <code>pucRegBuffer</code>.
+ * If the buffer should be written by the callback function unused
+ * coil values (I.e. if not a multiple of eight coils is used) should be set
+ * to zero.
+ * \param usAddress The first coil number.
+ * \param usNCoils Number of coil values requested.
+ * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should
+ * be updated from the values supplied in the buffer \c pucRegBuffer.
+ * If eMBRegisterMode::MB_REG_READ the application should store the current
+ * values in the buffer \c pucRegBuffer.
+ *
+ * \return The function must return one of the following error codes:
+ * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ * Modbus response is sent.
+ * - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ * within the requested address range. In this case a
+ * <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNCoils, eMBRegisterMode eMode );
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if a <em>Input Discrete Register</em> value is
+ * read by the protocol stack.
+ *
+ * If you are going to use his function you might use the functions
+ * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields.
+ *
+ * \param pucRegBuffer The buffer should be updated with the current
+ * coil values. The first discrete input starting at \c usAddress must be
+ * stored at the LSB of the first byte in the buffer. If the requested number
+ * is not a multiple of eight the remaining bits should be set to zero.
+ * \param usAddress The starting address of the first discrete input.
+ * \param usNDiscrete Number of discrete input values.
+ * \return The function must return one of the following error codes:
+ * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ * Modbus response is sent.
+ * - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ * within the requested address range. In this case a
+ * <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNDiscrete );
/*! \ingroup modbus
*\brief These Modbus functions are called for user when Modbus run in Master Mode.
*/
eMBMasterReqErrCode
-eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs );
+eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
-eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData );
+eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
eMBMasterReqErrCode
-eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer );
+eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr,
+ USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
-eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs );
+eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
- USHORT usWriteRegAddr, USHORT usNWriteRegs );
+ USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut );
eMBMasterReqErrCode
-eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils );
+eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut );
eMBMasterReqErrCode
-eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData );
+eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
- USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer );
+ USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
-eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn );
+eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut );
eMBException
eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen );
@@ -239,16 +381,18 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
/*�� \ingroup modbus
*\brief These functions are interface for Modbus Master
*/
-BOOL xMBMasterGetIsBusy( void );
void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame );
UCHAR ucMBMasterGetDestAddress( void );
void vMBMasterSetDestAddress( UCHAR Address );
-void vMBMasterSetIsBusy( BOOL IsBusy );
BOOL xMBMasterGetCBRunInMasterMode( void );
void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode );
-UCHAR ucMBMasterGetPDUSndLength( void );
-void vMBMasterSetPDUSndLength( UCHAR SendPDULength );
+USHORT usMBMasterGetPDUSndLength( void );
+void vMBMasterSetPDUSndLength( USHORT SendPDULength );
void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode );
+BOOL xMBMasterRequestIsBroadcast( void );
+eMBMasterErrorEventType eMBMasterGetErrorType( void );
+void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
+eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
/* ----------------------- Callback -----------------------------------------*/
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h b/components/net/freemodbus/modbus/include/mbconfig.h
index c5434de47e..89030b7abd 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h
+++ b/components/net/freemodbus/modbus/include/mbconfig.h
@@ -115,9 +115,9 @@ PR_BEGIN_EXTERN_C
/*! \brief If master send a frame which is not broadcast,the master will wait sometime for slave.
* And if slave is not respond in this time,the master will process this timeout error.
* Then master can send other frame */
-#define MB_MASTER_TIMEOUT_MS_RESPOND (2000)
-/*! \brief The total slaves in Modbus Master system.Default 16.
- * Note : The slave ID must be continuous from 0.*/
+#define MB_MASTER_TIMEOUT_MS_RESPOND (100 )
+/*! \brief The total slaves in Modbus Master system. Default 16.
+ * \note : The slave ID must be continuous from 1.*/
#define MB_MASTER_TOTAL_SLAVE_NUM ( 16 )
#endif
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbframe.h b/components/net/freemodbus/modbus/include/mbframe.h
index 99d59c613e..99d59c613e 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mbframe.h
+++ b/components/net/freemodbus/modbus/include/mbframe.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbfunc.h b/components/net/freemodbus/modbus/include/mbfunc.h
index 3f9c2725a1..3f9c2725a1 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mbfunc.h
+++ b/components/net/freemodbus/modbus/include/mbfunc.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbport.h b/components/net/freemodbus/modbus/include/mbport.h
index a4c0a24dd4..11794a2929 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mbport.h
+++ b/components/net/freemodbus/modbus/include/mbport.h
@@ -36,25 +36,38 @@
PR_BEGIN_EXTERN_C
#endif
+/* ----------------------- Defines ------------------------------------------*/
+
/* ----------------------- Type definitions ---------------------------------*/
typedef enum
{
- EV_READY, /*!< Startup finished. */
- EV_FRAME_RECEIVED, /*!< Frame received. */
- EV_EXECUTE, /*!< Execute function. */
- EV_FRAME_SENT /*!< Frame sent. */
+ EV_READY = 1<<0, /*!< Startup finished. */
+ EV_FRAME_RECEIVED = 1<<1, /*!< Frame received. */
+ EV_EXECUTE = 1<<2, /*!< Execute function. */
+ EV_FRAME_SENT = 1<<3 /*!< Frame sent. */
} eMBEventType;
typedef enum
{
- EV_MASTER_READY, /*!< Startup finished. */
- EV_MASTER_FRAME_RECEIVED, /*!< Frame received. */
- EV_MASTER_EXECUTE, /*!< Execute function. */
- EV_MASTER_FRAME_SENT, /*!< Frame sent. */
- EV_MASTER_ERROR_PROCESS /*!< Frame error process*/
+ EV_MASTER_READY = 1<<0, /*!< Startup finished. */
+ EV_MASTER_FRAME_RECEIVED = 1<<1, /*!< Frame received. */
+ EV_MASTER_EXECUTE = 1<<2, /*!< Execute function. */
+ EV_MASTER_FRAME_SENT = 1<<3, /*!< Frame sent. */
+ EV_MASTER_ERROR_PROCESS = 1<<4, /*!< Frame error process. */
+ EV_MASTER_PROCESS_SUCESS = 1<<5, /*!< Request process success. */
+ EV_MASTER_ERROR_RESPOND_TIMEOUT = 1<<6, /*!< Request respond timeout. */
+ EV_MASTER_ERROR_RECEIVE_DATA = 1<<7, /*!< Request receive data error. */
+ EV_MASTER_ERROR_EXECUTE_FUNCTION = 1<<8, /*!< Request execute function error. */
} eMBMasterEventType;
+typedef enum
+{
+ EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */
+ EV_ERROR_RECEIVE_DATA, /*!< Receive frame data erroe. */
+ EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */
+} eMBMasterErrorEventType;
+
/*! \ingroup modbus
* \brief Parity used for characters in serial mode.
*
@@ -82,6 +95,12 @@ BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent );
BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent );
+void vMBMasterOsResInit( void );
+
+BOOL xMBMasterRunResTake( int32_t time );
+
+void vMBMasterRunResRelease( void );
+
/* ----------------------- Serial port functions ----------------------------*/
BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
@@ -97,7 +116,6 @@ INLINE BOOL xMBPortSerialGetByte( CHAR * pucByte );
INLINE BOOL xMBPortSerialPutByte( CHAR ucByte );
-
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
UCHAR ucDataBits, eMBParity eParity );
@@ -132,6 +150,18 @@ INLINE void vMBMasterPortTimersRespondTimeoutEnable( void );
INLINE void vMBMasterPortTimersDisable( void );
+/* ----------------- Callback for the master error process ------------------*/
+void vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData,
+ USHORT ucPDULength );
+
+void vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData,
+ USHORT ucPDULength );
+
+void vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData,
+ USHORT ucPDULength );
+
+void vMBMasterCBRequestScuuess( void );
+
/* ----------------------- Callback for the protocol stack ------------------*/
/*!
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbproto.h b/components/net/freemodbus/modbus/include/mbproto.h
index 786aaf4030..786aaf4030 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mbproto.h
+++ b/components/net/freemodbus/modbus/include/mbproto.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbutils.h b/components/net/freemodbus/modbus/include/mbutils.h
index 61495751d4..61495751d4 100644
--- a/components/net/freemodbus-v1.6.0/modbus/include/mbutils.h
+++ b/components/net/freemodbus/modbus/include/mbutils.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/mb.c b/components/net/freemodbus/modbus/mb.c
index 96d693c910..96d693c910 100644
--- a/components/net/freemodbus-v1.6.0/modbus/mb.c
+++ b/components/net/freemodbus/modbus/mb.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/mb_m.c b/components/net/freemodbus/modbus/mb_m.c
index 8f86f54182..4e7c4b2b74 100644
--- a/components/net/freemodbus-v1.6.0/modbus/mb_m.c
+++ b/components/net/freemodbus/modbus/mb_m.c
@@ -65,7 +65,7 @@
static UCHAR ucMBMasterDestAddress;
static BOOL xMBRunInMasterMode = FALSE;
-static BOOL xMasterIsBusy = FALSE;
+static eMBMasterErrorEventType eMBMasterCurErrorType;
static enum
{
@@ -185,6 +185,8 @@ eMBMasterInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity
{
eMBState = STATE_DISABLED;
}
+ /* initialize the OS resource for modbus master. */
+ vMBMasterOsResInit();
}
return eStatus;
}
@@ -257,9 +259,10 @@ eMBMasterPoll( void )
static USHORT usLength;
static eMBException eException;
- int i;
+ int i , j;
eMBErrorCode eStatus = MB_ENOERR;
eMBMasterEventType eEvent;
+ eMBMasterErrorEventType errorType;
/* Check if the protocol stack is ready. */
if( eMBState != STATE_ENABLED )
@@ -285,6 +288,7 @@ eMBMasterPoll( void )
}
else
{
+ vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
}
break;
@@ -292,52 +296,80 @@ eMBMasterPoll( void )
case EV_MASTER_EXECUTE:
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
eException = MB_EX_ILLEGAL_FUNCTION;
- for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
- {
- /* No more function handlers registered. Abort. */
- if( xMasterFuncHandlers[i].ucFunctionCode == 0 )
- {
- break;
- }
- else if( xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode )
- {
- vMBMasterSetCBRunInMasterMode(TRUE);
- eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
- vMBMasterSetCBRunInMasterMode(FALSE);
- break;
- }
- }
/* If receive frame has exception .The receive function code highest bit is 1.*/
- if(ucFunctionCode >> 7) eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
+ if(ucFunctionCode >> 7) {
+ eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
+ }
+ else
+ {
+ for (i = 0; i < MB_FUNC_HANDLERS_MAX; i++)
+ {
+ /* No more function handlers registered. Abort. */
+ if (xMasterFuncHandlers[i].ucFunctionCode == 0) {
+ break;
+ }
+ else if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) {
+ vMBMasterSetCBRunInMasterMode(TRUE);
+ /* If master request is broadcast,
+ * the master need execute function for all slave.
+ */
+ if ( xMBMasterRequestIsBroadcast() ) {
+ usLength = usMBMasterGetPDUSndLength();
+ for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++){
+ vMBMasterSetDestAddress(j);
+ eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
+ }
+ }
+ else {
+ eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
+ }
+ vMBMasterSetCBRunInMasterMode(FALSE);
+ break;
+ }
+ }
+ }
/* If master has exception ,Master will send error process.Otherwise the Master is idle.*/
- if (eException != MB_EX_NONE) ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
- else vMBMasterSetIsBusy( FALSE );
+ if (eException != MB_EX_NONE) {
+ vMBMasterSetErrorType(EV_ERROR_EXECUTE_FUNCTION);
+ ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
+ }
+ else {
+ vMBMasterCBRequestScuuess( );
+ vMBMasterRunResRelease( );
+ }
break;
case EV_MASTER_FRAME_SENT:
/* Master is busy now. */
- vMBMasterSetIsBusy( TRUE );
vMBMasterGetPDUSndBuf( &ucMBFrame );
- eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, ucMBMasterGetPDUSndLength() );
+ eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
break;
case EV_MASTER_ERROR_PROCESS:
- vMBMasterSetIsBusy( FALSE );
+ /* Execute specified error process callback function. */
+ errorType = eMBMasterGetErrorType();
+ vMBMasterGetPDUSndBuf( &ucMBFrame );
+ switch (errorType) {
+ case EV_ERROR_RESPOND_TIMEOUT:
+ vMBMasterErrorCBRespondTimeout(ucMBMasterGetDestAddress(),
+ ucMBFrame, usMBMasterGetPDUSndLength());
+ break;
+ case EV_ERROR_RECEIVE_DATA:
+ vMBMasterErrorCBReceiveData(ucMBMasterGetDestAddress(),
+ ucMBFrame, usMBMasterGetPDUSndLength());
+ break;
+ case EV_ERROR_EXECUTE_FUNCTION:
+ vMBMasterErrorCBExecuteFunction(ucMBMasterGetDestAddress(),
+ ucMBFrame, usMBMasterGetPDUSndLength());
+ break;
+ }
+ vMBMasterRunResRelease();
break;
}
}
return MB_ENOERR;
}
-/* Get whether the Modbus Master is busy.*/
-BOOL xMBMasterGetIsBusy( void )
-{
- return xMasterIsBusy;
-}
-/* Set whether the Modbus Master is busy.*/
-void vMBMasterSetIsBusy( BOOL IsBusy )
-{
- xMasterIsBusy = IsBusy;
-}
+
/* Get whether the Modbus Master is run in master mode.*/
BOOL xMBMasterGetCBRunInMasterMode( void )
{
@@ -348,15 +380,27 @@ void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode )
{
xMBRunInMasterMode = IsMasterMode;
}
-/* Get Modbus Master send destination address*/
+/* Get Modbus Master send destination address. */
UCHAR ucMBMasterGetDestAddress( void )
{
return ucMBMasterDestAddress;
}
-/* Set Modbus Master send destination address*/
+/* Set Modbus Master send destination address. */
void vMBMasterSetDestAddress( UCHAR Address )
{
ucMBMasterDestAddress = Address;
}
+/* Get Modbus Master current error event type. */
+eMBMasterErrorEventType eMBMasterGetErrorType( void )
+{
+ return eMBMasterCurErrorType;
+}
+/* Set Modbus Master current error event type. */
+void vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
+{
+ eMBMasterCurErrorType = errorType;
+}
+
+
#endif
diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbcrc.c b/components/net/freemodbus/modbus/rtu/mbcrc.c
index 29b9ea765a..29b9ea765a 100644
--- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbcrc.c
+++ b/components/net/freemodbus/modbus/rtu/mbcrc.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbcrc.h b/components/net/freemodbus/modbus/rtu/mbcrc.h
index db227763f1..db227763f1 100644
--- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbcrc.h
+++ b/components/net/freemodbus/modbus/rtu/mbcrc.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu.c b/components/net/freemodbus/modbus/rtu/mbrtu.c
index c023c92654..c023c92654 100644
--- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu.c
+++ b/components/net/freemodbus/modbus/rtu/mbrtu.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu.h b/components/net/freemodbus/modbus/rtu/mbrtu.h
index 98c43de4aa..98c43de4aa 100644
--- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu.h
+++ b/components/net/freemodbus/modbus/rtu/mbrtu.h
diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c b/components/net/freemodbus/modbus/rtu/mbrtu_m.c
index fffbb23f9f..987c9a3156 100644
--- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c
+++ b/components/net/freemodbus/modbus/rtu/mbrtu_m.c
@@ -74,7 +74,7 @@ static volatile eMBMasterRcvState eRcvState;
static volatile UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX];
static volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX];
-static volatile UCHAR ucMasterSendPDULength;
+static volatile USHORT usMasterSendPDULength;
static volatile UCHAR *pucMasterSndBufferCur;
static volatile USHORT usMasterSndBufferCount;
@@ -235,7 +235,7 @@ xMBMasterRTUReceiveFSM( void )
BOOL xTaskNeedSwitch = FALSE;
UCHAR ucByte;
- assert_param( eSndState == STATE_M_TX_IDLE );
+ assert_param(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR ));
/* Always read the character. */
( void )xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte );
@@ -364,12 +364,15 @@ xMBMasterRTUTimerExpired(void)
/* An error occured while receiving the frame. */
case STATE_M_RX_ERROR:
+ vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
+ xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
break;
/* Function called in an illegal state. */
default:
assert_param(
- ( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) || ( eRcvState == STATE_M_RX_ERROR ));
+ ( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) ||
+ ( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE ));
break;
}
eRcvState = STATE_M_RX_IDLE;
@@ -380,18 +383,24 @@ xMBMasterRTUTimerExpired(void)
* If the frame is broadcast,The master will idle,and if the frame is not
* broadcast.Notify the listener process error.*/
case STATE_M_TX_XFWR:
- if ( xFrameIsBroadcast == FALSE ) xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
+ if ( xFrameIsBroadcast == FALSE ) {
+ vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT);
+ xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
+ }
break;
/* Function called in an illegal state. */
default:
- assert_param( eSndState == STATE_M_TX_XFWR );
+ assert_param(
+ ( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE ));
break;
}
eSndState = STATE_M_TX_IDLE;
vMBMasterPortTimersDisable( );
- /* If timer mode is convert delay ,then Master is idel now. */
- if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) vMBMasterSetIsBusy( FALSE );
+ /* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */
+ if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) {
+ xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE );
+ }
return xNeedPoll;
}
@@ -409,15 +418,15 @@ void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
}
/* Set Modbus Master send PDU's buffer length.*/
-void vMBMasterSetPDUSndLength( UCHAR SendPDULength )
+void vMBMasterSetPDUSndLength( USHORT SendPDULength )
{
- ucMasterSendPDULength = SendPDULength;
+ usMasterSendPDULength = SendPDULength;
}
/* Get Modbus Master send PDU's buffer length.*/
-UCHAR ucMBMasterGetPDUSndLength( void )
+USHORT usMBMasterGetPDUSndLength( void )
{
- return ucMasterSendPDULength;
+ return usMasterSendPDULength;
}
/* Set Modbus Master current timer mode.*/
@@ -425,5 +434,10 @@ void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
{
eMasterCurTimerMode = eMBTimerMode;
}
+
+/* The master request is broadcast? */
+BOOL xMBMasterRequestIsBroadcast( void ){
+ return xFrameIsBroadcast;
+}
#endif
diff --git a/components/net/freemodbus-v1.6.0/modbus/tcp/mbtcp.c b/components/net/freemodbus/modbus/tcp/mbtcp.c
index 3eb3b7071f..3eb3b7071f 100644
--- a/components/net/freemodbus-v1.6.0/modbus/tcp/mbtcp.c
+++ b/components/net/freemodbus/modbus/tcp/mbtcp.c
diff --git a/components/net/freemodbus-v1.6.0/modbus/tcp/mbtcp.h b/components/net/freemodbus/modbus/tcp/mbtcp.h
index 905d113c5a..905d113c5a 100644
--- a/components/net/freemodbus-v1.6.0/modbus/tcp/mbtcp.h
+++ b/components/net/freemodbus/modbus/tcp/mbtcp.h
diff --git a/components/net/freemodbus-v1.6.0/port/port.c b/components/net/freemodbus/port/port.c
index 459481cc1d..d01c5c9d6a 100644
--- a/components/net/freemodbus-v1.6.0/port/port.c
+++ b/components/net/freemodbus/port/port.c
@@ -1,6 +1,6 @@
/*
- * FreeModbus Libary: LPC214X Port
- * Copyright (C) 2007 Tiago Prado Lone <[email protected]>
+ * FreeModbus Libary: RT-Thread Port
+ * Copyright (C) 2013 Armink <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
- * File: $Id: port.c,v 1.1 2007/04/24 23:15:18 wolti Exp $
+ * File: $Id: port.c,v 1.60 2015/02/01 9:18:05 Armink $
*/
/* ----------------------- System includes --------------------------------*/
@@ -24,16 +24,15 @@
/* ----------------------- Modbus includes ----------------------------------*/
#include "port.h"
/* ----------------------- Variables ----------------------------------------*/
-
+static rt_base_t level;
/* ----------------------- Start implementation -----------------------------*/
void EnterCriticalSection(void)
{
- //�ر�ȫ���ж�
- __disable_irq();
+ level = rt_hw_interrupt_disable();
}
void ExitCriticalSection(void)
{
- //����ȫ���ж�
- __enable_irq();
+ rt_hw_interrupt_enable(level);
}
+
diff --git a/components/net/freemodbus-v1.6.0/port/port.h b/components/net/freemodbus/port/port.h
index c79df3d887..73d2177c9a 100644
--- a/components/net/freemodbus-v1.6.0/port/port.h
+++ b/components/net/freemodbus/port/port.h
@@ -1,6 +1,6 @@
/*
* FreeModbus Libary: BARE Port
- * Copyright (C) 2006 Christian Walter <[email protected]>
+ * Copyright (C) 2013 Armink <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -30,22 +30,13 @@
#include <assert.h>
#include <inttypes.h>
-#define INLINE
+#define INLINE
#define PR_BEGIN_EXTERN_C extern "C" {
-#define PR_END_EXTERN_C }
+#define PR_END_EXTERN_C }
-//TODO ��ʱ��дB13���ţ�����������ʱ��ȷ��
-#define SLAVE_RS485_SEND_MODE GPIO_SetBits(GPIOB,GPIO_Pin_13)
-#define SLAVE_RS485_RECEIVE_MODE GPIO_ResetBits(GPIOB,GPIO_Pin_13)
-#define MASTER_RS485_SEND_MODE GPIO_SetBits(GPIOB,GPIO_Pin_13)
-#define MASTER_RS485_RECEIVE_MODE GPIO_ResetBits(GPIOB,GPIO_Pin_13)
-
-#define ENTER_CRITICAL_SECTION() EnterCriticalSection()
+#define ENTER_CRITICAL_SECTION() EnterCriticalSection()
#define EXIT_CRITICAL_SECTION() ExitCriticalSection()
-void EnterCriticalSection(void);
-void ExitCriticalSection(void);
-
typedef uint8_t BOOL;
typedef unsigned char UCHAR;
@@ -65,4 +56,7 @@ typedef int32_t LONG;
#define FALSE 0
#endif
+void EnterCriticalSection(void);
+void ExitCriticalSection(void);
+
#endif
diff --git a/components/net/freemodbus-v1.6.0/port/portevent.c b/components/net/freemodbus/port/portevent.c
index 86c7b5e7a5..1a881166be 100644
--- a/components/net/freemodbus-v1.6.0/port/portevent.c
+++ b/components/net/freemodbus/port/portevent.c
@@ -1,5 +1,5 @@
/*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
* Copyright (C) 2013 Armink <[email protected]>
*
* This library is free software; you can redistribute it and/or
@@ -24,35 +24,45 @@
#include "mbport.h"
/* ----------------------- Variables ----------------------------------------*/
-static eMBEventType eQueuedEvent;
-static BOOL xEventInQueue;
-
+static struct rt_event xSlaveOsEvent;
/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortEventInit( void )
{
- xEventInQueue = FALSE;
+ rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO);
return TRUE;
}
BOOL
xMBPortEventPost( eMBEventType eEvent )
{
- xEventInQueue = TRUE;
- eQueuedEvent = eEvent;
+ rt_event_send(&xSlaveOsEvent, eEvent);
return TRUE;
}
BOOL
xMBPortEventGet( eMBEventType * eEvent )
{
- BOOL xEventHappened = FALSE;
-
- if( xEventInQueue )
+ rt_uint32_t recvedEvent;
+ /* waiting forever OS event */
+ rt_event_recv(&xSlaveOsEvent,
+ EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT,
+ RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+ &recvedEvent);
+ switch (recvedEvent)
{
- *eEvent = eQueuedEvent;
- xEventInQueue = FALSE;
- xEventHappened = TRUE;
+ case EV_READY:
+ *eEvent = EV_READY;
+ break;
+ case EV_FRAME_RECEIVED:
+ *eEvent = EV_FRAME_RECEIVED;
+ break;
+ case EV_EXECUTE:
+ *eEvent = EV_EXECUTE;
+ break;
+ case EV_FRAME_SENT:
+ *eEvent = EV_FRAME_SENT;
+ break;
}
- return xEventHappened;
+ return TRUE;
}
diff --git a/components/net/freemodbus/port/portevent_m.c b/components/net/freemodbus/port/portevent_m.c
new file mode 100644
index 0000000000..031a3b84ef
--- /dev/null
+++ b/components/net/freemodbus/port/portevent_m.c
@@ -0,0 +1,239 @@
+/*
+ * FreeModbus Libary: RT-Thread Port
+ * Copyright (C) 2013 Armink <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * File: $Id: portevent_m.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions$
+ */
+
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mb_m.h"
+#include "mbport.h"
+#include "port.h"
+
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Defines ------------------------------------------*/
+/* ----------------------- Variables ----------------------------------------*/
+static struct rt_semaphore xMasterRunRes;
+static struct rt_event xMasterOsEvent;
+/* ----------------------- Start implementation -----------------------------*/
+BOOL
+xMBMasterPortEventInit( void )
+{
+ rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO);
+ return TRUE;
+}
+
+BOOL
+xMBMasterPortEventPost( eMBMasterEventType eEvent )
+{
+ rt_event_send(&xMasterOsEvent, eEvent);
+ return TRUE;
+}
+
+BOOL
+xMBMasterPortEventGet( eMBMasterEventType * eEvent )
+{
+ rt_uint32_t recvedEvent;
+ /* waiting forever OS event */
+ rt_event_recv(&xMasterOsEvent,
+ EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE |
+ EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS,
+ RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+ &recvedEvent);
+ /* the enum type couldn't convert to int type */
+ switch (recvedEvent)
+ {
+ case EV_MASTER_READY:
+ *eEvent = EV_MASTER_READY;
+ break;
+ case EV_MASTER_FRAME_RECEIVED:
+ *eEvent = EV_MASTER_FRAME_RECEIVED;
+ break;
+ case EV_MASTER_EXECUTE:
+ *eEvent = EV_MASTER_EXECUTE;
+ break;
+ case EV_MASTER_FRAME_SENT:
+ *eEvent = EV_MASTER_FRAME_SENT;
+ break;
+ case EV_MASTER_ERROR_PROCESS:
+ *eEvent = EV_MASTER_ERROR_PROCESS;
+ break;
+ }
+ return TRUE;
+}
+/**
+ * This function is initialize the OS resource for modbus master.
+ * Note:The resource is define by OS.If you not use OS this function can be empty.
+ *
+ */
+void vMBMasterOsResInit( void )
+{
+ rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO);
+}
+
+/**
+ * This function is take Mobus Master running resource.
+ * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE.
+ *
+ * @param lTimeOut the waiting time.
+ *
+ * @return resource taked result
+ */
+BOOL xMBMasterRunResTake( LONG lTimeOut )
+{
+ /*If waiting time is -1 .It will wait forever */
+ return rt_sem_take(&xMasterRunRes, lTimeOut) ? FALSE : TRUE ;
+}
+
+/**
+ * This function is release Mobus Master running resource.
+ * Note:The resource is define by Operating System.If you not use OS this function can be empty.
+ *
+ */
+void vMBMasterRunResRelease( void )
+{
+ /* release resource */
+ rt_sem_release(&xMasterRunRes);
+}
+
+/**
+ * This is modbus master respond timeout error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+ USHORT ucPDULength) {
+ /**
+ * @note This code is use OS's event mechanism for modbus master protocol stack.
+ * If you don't use OS, you can change it.
+ */
+ rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT);
+
+ /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master receive data error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+ USHORT ucPDULength) {
+ /**
+ * @note This code is use OS's event mechanism for modbus master protocol stack.
+ * If you don't use OS, you can change it.
+ */
+ rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA);
+
+ /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master execute function error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+ USHORT ucPDULength) {
+ /**
+ * @note This code is use OS's event mechanism for modbus master protocol stack.
+ * If you don't use OS, you can change it.
+ */
+ rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION);
+
+ /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master request process success callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ */
+void vMBMasterCBRequestScuuess( void ) {
+ /**
+ * @note This code is use OS's event mechanism for modbus master protocol stack.
+ * If you don't use OS, you can change it.
+ */
+ rt_event_send(&xMasterOsEvent, EV_MASTER_PROCESS_SUCESS);
+
+ /* You can add your code under here. */
+
+}
+
+/**
+ * This function is wait for modbus master request finish and return result.
+ * Waiting result include request process success, request respond timeout,
+ * receive data error and execute function error.You can use the above callback function.
+ * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run
+ * much user custom delay for waiting.
+ *
+ * @return request error code
+ */
+eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
+ eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
+ rt_uint32_t recvedEvent;
+ /* waiting for OS event */
+ rt_event_recv(&xMasterOsEvent,
+ EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT
+ | EV_MASTER_ERROR_RECEIVE_DATA
+ | EV_MASTER_ERROR_EXECUTE_FUNCTION,
+ RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+ &recvedEvent);
+ switch (recvedEvent)
+ {
+ case EV_MASTER_PROCESS_SUCESS:
+ break;
+ case EV_MASTER_ERROR_RESPOND_TIMEOUT:
+ {
+ eErrStatus = MB_MRE_TIMEDOUT;
+ break;
+ }
+ case EV_MASTER_ERROR_RECEIVE_DATA:
+ {
+ eErrStatus = MB_MRE_REV_DATA;
+ break;
+ }
+ case EV_MASTER_ERROR_EXECUTE_FUNCTION:
+ {
+ eErrStatus = MB_MRE_EXE_FUN;
+ break;
+ }
+ }
+ return eErrStatus;
+}
+
+#endif
diff --git a/components/net/freemodbus/port/portserial.c b/components/net/freemodbus/port/portserial.c
new file mode 100644
index 0000000000..317c7f4605
--- /dev/null
+++ b/components/net/freemodbus/port/portserial.c
@@ -0,0 +1,222 @@
+/*
+ * FreeModbus Libary: RT-Thread Port
+ * Copyright (C) 2013 Armink <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $
+ */
+
+#include "port.h"
+
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mbport.h"
+#include "rtdevice.h"
+#include "board.h"
+
+/* ----------------------- Static variables ---------------------------------*/
+ALIGN(RT_ALIGN_SIZE)
+/* software simulation serial transmit IRQ handler thread stack */
+static rt_uint8_t serial_soft_trans_irq_stack[512];
+/* software simulation serial transmit IRQ handler thread */
+static struct rt_thread thread_serial_soft_trans_irq;
+/* serial event */
+static struct rt_event event_serial;
+/* modbus slave serial device */
+static rt_serial_t *serial;
+
+/* ----------------------- Defines ------------------------------------------*/
+/* serial transmit event */
+#define EVENT_SERIAL_TRANS_START (1<<0)
+
+/* ----------------------- static functions ---------------------------------*/
+static void prvvUARTTxReadyISR(void);
+static void prvvUARTRxISR(void);
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
+static void serial_soft_trans_irq(void* parameter);
+
+/* ----------------------- Start implementation -----------------------------*/
+BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
+ eMBParity eParity)
+{
+ /**
+ * set 485 mode receive and transmit control IO
+ * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user
+ */
+ rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
+
+ /* set serial name */
+ if (ucPORT == 1) {
+#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
+ extern struct rt_serial_device serial1;
+ serial = &serial1;
+#endif
+ } else if (ucPORT == 2) {
+#if defined(RT_USING_UART2)
+ extern struct rt_serial_device serial2;
+ serial = &serial2;
+#endif
+ } else if (ucPORT == 3) {
+#if defined(RT_USING_UART3)
+ extern struct rt_serial_device serial3;
+ serial = &serial3;
+#endif
+ }
+ /* set serial configure parameter */
+ serial->config.baud_rate = ulBaudRate;
+ serial->config.stop_bits = STOP_BITS_1;
+ switch(eParity){
+ case MB_PAR_NONE: {
+ serial->config.data_bits = DATA_BITS_8;
+ serial->config.parity = PARITY_NONE;
+ break;
+ }
+ case MB_PAR_ODD: {
+ serial->config.data_bits = DATA_BITS_9;
+ serial->config.parity = PARITY_ODD;
+ break;
+ }
+ case MB_PAR_EVEN: {
+ serial->config.data_bits = DATA_BITS_9;
+ serial->config.parity = PARITY_EVEN;
+ break;
+ }
+ }
+ /* set serial configure */
+ serial->ops->configure(serial, &(serial->config));
+
+ /* open serial device */
+ if (!serial->parent.open(&serial->parent,
+ RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) {
+ serial->parent.rx_indicate = serial_rx_ind;
+ } else {
+ return FALSE;
+ }
+
+ /* software initialize */
+ rt_thread_init(&thread_serial_soft_trans_irq,
+ "slave trans",
+ serial_soft_trans_irq,
+ RT_NULL,
+ serial_soft_trans_irq_stack,
+ sizeof(serial_soft_trans_irq_stack),
+ 10, 5);
+ rt_thread_startup(&thread_serial_soft_trans_irq);
+ rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
+
+ return TRUE;
+}
+
+void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
+{
+ rt_uint32_t recved_event;
+ if (xRxEnable)
+ {
+ /* enable RX interrupt */
+ serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+ /* switch 485 to receive mode */
+ rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW);
+ }
+ else
+ {
+ /* switch 485 to transmit mode */
+ rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH);
+ /* disable RX interrupt */
+ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+ }
+ if (xTxEnable)
+ {
+ /* start serial transmit */
+ rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
+ }
+ else
+ {
+ /* stop serial transmit */
+ rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
+ RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
+ &recved_event);
+ }
+}
+
+void vMBPortClose(void)
+{
+ serial->parent.close(&(serial->parent));
+}
+
+BOOL xMBPortSerialPutByte(CHAR ucByte)
+{
+ serial->parent.write(&(serial->parent), 0, &ucByte, 1);
+ return TRUE;
+}
+
+BOOL xMBPortSerialGetByte(CHAR * pucByte)
+{
+ serial->parent.read(&(serial->parent), 0, pucByte, 1);
+ return TRUE;
+}
+
+/*
+ * Create an interrupt handler for the transmit buffer empty interrupt
+ * (or an equivalent) for your target processor. This function should then
+ * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
+ * a new character can be sent. The protocol stack will then call
+ * xMBPortSerialPutByte( ) to send the character.
+ */
+void prvvUARTTxReadyISR(void)
+{
+ pxMBFrameCBTransmitterEmpty();
+}
+
+/*
+ * Create an interrupt handler for the receive interrupt for your target
+ * processor. This function should then call pxMBFrameCBByteReceived( ). The
+ * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
+ * character.
+ */
+void prvvUARTRxISR(void)
+{
+ pxMBFrameCBByteReceived();
+}
+
+/**
+ * Software simulation serial transmit IRQ handler.
+ *
+ * @param parameter parameter
+ */
+static void serial_soft_trans_irq(void* parameter) {
+ rt_uint32_t recved_event;
+ while (1)
+ {
+ /* waiting for serial transmit start */
+ rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
+ RT_WAITING_FOREVER, &recved_event);
+ /* execute modbus callback */
+ prvvUARTTxReadyISR();
+ }
+}
+
+/**
+ * This function is serial receive callback function
+ *
+ * @param dev the device of serial
+ * @param size the data size that receive
+ *
+ * @return return RT_EOK
+ */
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
+ prvvUARTRxISR();
+ return RT_EOK;
+}
diff --git a/components/net/freemodbus/port/portserial_m.c b/components/net/freemodbus/port/portserial_m.c
new file mode 100644
index 0000000000..8ec0d081f1
--- /dev/null
+++ b/components/net/freemodbus/port/portserial_m.c
@@ -0,0 +1,225 @@
+/*
+ * FreeModbus Libary: RT-Thread Port
+ * Copyright (C) 2013 Armink <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * File: $Id: portserial_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $
+ */
+
+#include "port.h"
+
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mbport.h"
+#include "rtdevice.h"
+#include "board.h"
+
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Static variables ---------------------------------*/
+ALIGN(RT_ALIGN_SIZE)
+/* software simulation serial transmit IRQ handler thread stack */
+static rt_uint8_t serial_soft_trans_irq_stack[512];
+/* software simulation serial transmit IRQ handler thread */
+static struct rt_thread thread_serial_soft_trans_irq;
+/* serial event */
+static struct rt_event event_serial;
+/* modbus slave serial device */
+static rt_serial_t *serial;
+
+/* ----------------------- Defines ------------------------------------------*/
+/* serial transmit event */
+#define EVENT_SERIAL_TRANS_START (1<<0)
+
+/* ----------------------- static functions ---------------------------------*/
+static void prvvUARTTxReadyISR(void);
+static void prvvUARTRxISR(void);
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
+static void serial_soft_trans_irq(void* parameter);
+
+/* ----------------------- Start implementation -----------------------------*/
+BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
+ eMBParity eParity)
+{
+ /**
+ * set 485 mode receive and transmit control IO
+ * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user
+ */
+ rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
+
+ /* set serial name */
+ if (ucPORT == 1) {
+#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
+ extern struct rt_serial_device serial1;
+ serial = &serial1;
+#endif
+ } else if (ucPORT == 2) {
+#if defined(RT_USING_UART2)
+ extern struct rt_serial_device serial2;
+ serial = &serial2;
+#endif
+ } else if (ucPORT == 3) {
+#if defined(RT_USING_UART3)
+ extern struct rt_serial_device serial3;
+ serial = &serial3;
+#endif
+ }
+ /* set serial configure parameter */
+ serial->config.baud_rate = ulBaudRate;
+ serial->config.stop_bits = STOP_BITS_1;
+ switch(eParity){
+ case MB_PAR_NONE: {
+ serial->config.data_bits = DATA_BITS_8;
+ serial->config.parity = PARITY_NONE;
+ break;
+ }
+ case MB_PAR_ODD: {
+ serial->config.data_bits = DATA_BITS_9;
+ serial->config.parity = PARITY_ODD;
+ break;
+ }
+ case MB_PAR_EVEN: {
+ serial->config.data_bits = DATA_BITS_9;
+ serial->config.parity = PARITY_EVEN;
+ break;
+ }
+ }
+ /* set serial configure */
+ serial->ops->configure(serial, &(serial->config));
+
+ /* open serial device */
+ if (!serial->parent.open(&serial->parent,
+ RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) {
+ serial->parent.rx_indicate = serial_rx_ind;
+ } else {
+ return FALSE;
+ }
+
+ /* software initialize */
+ rt_thread_init(&thread_serial_soft_trans_irq,
+ "slave trans",
+ serial_soft_trans_irq,
+ RT_NULL,
+ serial_soft_trans_irq_stack,
+ sizeof(serial_soft_trans_irq_stack),
+ 10, 5);
+ rt_thread_startup(&thread_serial_soft_trans_irq);
+ rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
+
+ return TRUE;
+}
+
+void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
+{
+ rt_uint32_t recved_event;
+ if (xRxEnable)
+ {
+ /* enable RX interrupt */
+ serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+ /* switch 485 to receive mode */
+ rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW);
+ }
+ else
+ {
+ /* switch 485 to transmit mode */
+ rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH);
+ /* disable RX interrupt */
+ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+ }
+ if (xTxEnable)
+ {
+ /* start serial transmit */
+ rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
+ }
+ else
+ {
+ /* stop serial transmit */
+ rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
+ RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
+ &recved_event);
+ }
+}
+
+void vMBMasterPortClose(void)
+{
+ serial->parent.close(&(serial->parent));
+}
+
+BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
+{
+ serial->parent.write(&(serial->parent), 0, &ucByte, 1);
+ return TRUE;
+}
+
+BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
+{
+ serial->parent.read(&(serial->parent), 0, pucByte, 1);
+ return TRUE;
+}
+
+/*
+ * Create an interrupt handler for the transmit buffer empty interrupt
+ * (or an equivalent) for your target processor. This function should then
+ * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
+ * a new character can be sent. The protocol stack will then call
+ * xMBPortSerialPutByte( ) to send the character.
+ */
+void prvvUARTTxReadyISR(void)
+{
+ pxMBMasterFrameCBTransmitterEmpty();
+}
+
+/*
+ * Create an interrupt handler for the receive interrupt for your target
+ * processor. This function should then call pxMBFrameCBByteReceived( ). The
+ * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
+ * character.
+ */
+void prvvUARTRxISR(void)
+{
+ pxMBMasterFrameCBByteReceived();
+}
+
+/**
+ * Software simulation serial transmit IRQ handler.
+ *
+ * @param parameter parameter
+ */
+static void serial_soft_trans_irq(void* parameter) {
+ rt_uint32_t recved_event;
+ while (1)
+ {
+ /* waiting for serial transmit start */
+ rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
+ RT_WAITING_FOREVER, &recved_event);
+ /* execute modbus callback */
+ prvvUARTTxReadyISR();
+ }
+}
+
+/**
+ * This function is serial receive callback function
+ *
+ * @param dev the device of serial
+ * @param size the data size that receive
+ *
+ * @return return RT_EOK
+ */
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
+ prvvUARTRxISR();
+ return RT_EOK;
+}
+
+#endif
diff --git a/components/net/freemodbus-v1.6.0/port/portevent_m.c b/components/net/freemodbus/port/porttimer.c
index c78b6cbcb2..6f017d8759 100644
--- a/components/net/freemodbus-v1.6.0/port/portevent_m.c
+++ b/components/net/freemodbus/port/porttimer.c
@@ -1,5 +1,5 @@
/*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
* Copyright (C) 2013 Armink <[email protected]>
*
* This library is free software; you can redistribute it and/or
@@ -16,46 +16,48 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
- * File: $Id: portevent_m.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions$
+ * File: $Id: porttimer.c,v 1.60 2013/08/13 15:07:05 Armink $
*/
+/* ----------------------- Platform includes --------------------------------*/
+#include "port.h"
+
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
-/* ----------------------- Variables ----------------------------------------*/
-static eMBMasterEventType eMasterQueuedEvent;
-static BOOL xMasterEventInQueue;
+/* ----------------------- static functions ---------------------------------*/
+static struct rt_timer timer;
+static void prvvTIMERExpiredISR(void);
+static void timer_timeout_ind(void* parameter);
/* ----------------------- Start implementation -----------------------------*/
-BOOL
-xMBMasterPortEventInit( void )
+BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
{
- xMasterEventInQueue = FALSE;
+ rt_timer_init(&timer, "slave timer",
+ timer_timeout_ind, /* bind timeout callback function */
+ RT_NULL,
+ (50*usTim1Timerout50us)/(1000*1000/RT_TICK_PER_SECOND),
+ RT_TIMER_FLAG_ONE_SHOT); /* one shot */
return TRUE;
}
-BOOL
-xMBMasterPortEventPost( eMBMasterEventType eEvent )
+void vMBPortTimersEnable()
{
- xMasterEventInQueue = TRUE;
- eMasterQueuedEvent = eEvent;
- return TRUE;
+ rt_timer_start(&timer);
}
-BOOL
-xMBMasterPortEventGet( eMBMasterEventType * eEvent )
+void vMBPortTimersDisable()
{
- BOOL xEventHappened = FALSE;
+ rt_timer_stop(&timer);
+}
- if( xMasterEventInQueue )
- {
- *eEvent = eMasterQueuedEvent;
- xMasterEventInQueue = FALSE;
- xEventHappened = TRUE;
- }
- return xEventHappened;
+void prvvTIMERExpiredISR(void)
+{
+ (void) pxMBPortCBTimerExpired();
}
-#endif
+static void timer_timeout_ind(void* parameter)
+{
+ prvvTIMERExpiredISR();
+}
diff --git a/components/net/freemodbus/port/porttimer_m.c b/components/net/freemodbus/port/porttimer_m.c
new file mode 100644
index 0000000000..00441bfd1c
--- /dev/null
+++ b/components/net/freemodbus/port/porttimer_m.c
@@ -0,0 +1,107 @@
+/*
+ * FreeModbus Libary: RT-Thread Port
+ * Copyright (C) 2013 Armink <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * File: $Id: porttimer_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$
+ */
+
+/* ----------------------- Platform includes --------------------------------*/
+#include "port.h"
+
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mb_m.h"
+#include "mbport.h"
+
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Variables ----------------------------------------*/
+static USHORT usT35TimeOut50us;
+static struct rt_timer timer;
+static void prvvTIMERExpiredISR(void);
+static void timer_timeout_ind(void* parameter);
+
+/* ----------------------- static functions ---------------------------------*/
+static void prvvTIMERExpiredISR(void);
+
+/* ----------------------- Start implementation -----------------------------*/
+BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
+{
+ /* backup T35 ticks */
+ usT35TimeOut50us = usTimeOut50us;
+
+ rt_timer_init(&timer, "master timer",
+ timer_timeout_ind, /* bind timeout callback function */
+ RT_NULL,
+ (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND),
+ RT_TIMER_FLAG_ONE_SHOT); /* one shot */
+
+ return TRUE;
+}
+
+void vMBMasterPortTimersT35Enable()
+{
+ rt_tick_t timer_tick = (50 * usT35TimeOut50us)
+ / (1000 * 1000 / RT_TICK_PER_SECOND);
+
+ /* Set current timer mode, don't change it.*/
+ vMBMasterSetCurTimerMode(MB_TMODE_T35);
+
+ rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
+
+ rt_timer_start(&timer);
+}
+
+void vMBMasterPortTimersConvertDelayEnable()
+{
+ rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000;
+
+ /* Set current timer mode, don't change it.*/
+ vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
+
+ rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
+
+ rt_timer_start(&timer);
+}
+
+void vMBMasterPortTimersRespondTimeoutEnable()
+{
+ rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000;
+
+ /* Set current timer mode, don't change it.*/
+ vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
+
+ rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
+
+ rt_timer_start(&timer);
+}
+
+void vMBMasterPortTimersDisable()
+{
+ rt_timer_stop(&timer);
+}
+
+void prvvTIMERExpiredISR(void)
+{
+ (void) pxMBMasterPortCBTimerExpired();
+}
+
+static void timer_timeout_ind(void* parameter)
+{
+ prvvTIMERExpiredISR();
+}
+
+#endif
diff --git a/components/net/freemodbus/port/user_mb_app.c b/components/net/freemodbus/port/user_mb_app.c
new file mode 100644
index 0000000000..8da7376336
--- /dev/null
+++ b/components/net/freemodbus/port/user_mb_app.c
@@ -0,0 +1,286 @@
+/*
+ * FreeModbus Libary: user callback functions and buffer define in slave mode
+ * Copyright (C) 2013 Armink <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $
+ */
+#include "user_mb_app.h"
+
+/*------------------------Slave mode use these variables----------------------*/
+//Slave mode:DiscreteInputs variables
+USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
+#if S_DISCRETE_INPUT_NDISCRETES%8
+UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1];
+#else
+UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ;
+#endif
+//Slave mode:Coils variables
+USHORT usSCoilStart = S_COIL_START;
+#if S_COIL_NCOILS%8
+UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ;
+#else
+UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ;
+#endif
+//Slave mode:InputRegister variables
+USHORT usSRegInStart = S_REG_INPUT_START;
+USHORT usSRegInBuf[S_REG_INPUT_NREGS] ;
+//Slave mode:HoldingRegister variables
+USHORT usSRegHoldStart = S_REG_HOLDING_START;
+USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ;
+
+/**
+ * Modbus slave input register callback function.
+ *
+ * @param pucRegBuffer input register buffer
+ * @param usAddress input register address
+ * @param usNRegs input register number
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex;
+ USHORT * pusRegInputBuf;
+ USHORT REG_INPUT_START;
+ USHORT REG_INPUT_NREGS;
+ USHORT usRegInStart;
+
+ pusRegInputBuf = usSRegInBuf;
+ REG_INPUT_START = S_REG_INPUT_START;
+ REG_INPUT_NREGS = S_REG_INPUT_NREGS;
+ usRegInStart = usSRegInStart;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= REG_INPUT_START)
+ && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
+ {
+ iRegIndex = usAddress - usRegInStart;
+ while (usNRegs > 0)
+ {
+ *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8);
+ *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF);
+ iRegIndex++;
+ usNRegs--;
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+
+ return eStatus;
+}
+
+/**
+ * Modbus slave holding register callback function.
+ *
+ * @param pucRegBuffer holding register buffer
+ * @param usAddress holding register address
+ * @param usNRegs holding register number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNRegs, eMBRegisterMode eMode)
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex;
+ USHORT * pusRegHoldingBuf;
+ USHORT REG_HOLDING_START;
+ USHORT REG_HOLDING_NREGS;
+ USHORT usRegHoldStart;
+
+ pusRegHoldingBuf = usSRegHoldBuf;
+ REG_HOLDING_START = S_REG_HOLDING_START;
+ REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
+ usRegHoldStart = usSRegHoldStart;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= REG_HOLDING_START)
+ && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
+ {
+ iRegIndex = usAddress - usRegHoldStart;
+ switch (eMode)
+ {
+ /* read current register values from the protocol stack. */
+ case MB_REG_READ:
+ while (usNRegs > 0)
+ {
+ *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
+ *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
+ iRegIndex++;
+ usNRegs--;
+ }
+ break;
+
+ /* write current register values with new values from the protocol stack. */
+ case MB_REG_WRITE:
+ while (usNRegs > 0)
+ {
+ pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
+ pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
+ iRegIndex++;
+ usNRegs--;
+ }
+ break;
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+ return eStatus;
+}
+
+/**
+ * Modbus slave coils callback function.
+ *
+ * @param pucRegBuffer coils buffer
+ * @param usAddress coils address
+ * @param usNCoils coils number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNCoils, eMBRegisterMode eMode)
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex , iRegBitIndex , iNReg;
+ UCHAR * pucCoilBuf;
+ USHORT COIL_START;
+ USHORT COIL_NCOILS;
+ USHORT usCoilStart;
+ iNReg = usNCoils / 8 + 1;
+
+ pucCoilBuf = ucSCoilBuf;
+ COIL_START = S_COIL_START;
+ COIL_NCOILS = S_COIL_NCOILS;
+ usCoilStart = usSCoilStart;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if( ( usAddress >= COIL_START ) &&
+ ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
+ {
+ iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
+ iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
+ switch ( eMode )
+ {
+ /* read current coil values from the protocol stack. */
+ case MB_REG_READ:
+ while (iNReg > 0)
+ {
+ *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
+ iRegBitIndex, 8);
+ iNReg--;
+ }
+ pucRegBuffer--;
+ /* last coils */
+ usNCoils = usNCoils % 8;
+ /* filling zero to high bit */
+ *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
+ *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
+ break;
+
+ /* write current coil values with new values from the protocol stack. */
+ case MB_REG_WRITE:
+ while (iNReg > 1)
+ {
+ xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
+ *pucRegBuffer++);
+ iNReg--;
+ }
+ /* last coils */
+ usNCoils = usNCoils % 8;
+ /* xMBUtilSetBits has bug when ucNBits is zero */
+ if (usNCoils != 0)
+ {
+ xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
+ *pucRegBuffer++);
+ }
+ break;
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+ return eStatus;
+}
+
+/**
+ * Modbus slave discrete callback function.
+ *
+ * @param pucRegBuffer discrete buffer
+ * @param usAddress discrete address
+ * @param usNDiscrete discrete number
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex , iRegBitIndex , iNReg;
+ UCHAR * pucDiscreteInputBuf;
+ USHORT DISCRETE_INPUT_START;
+ USHORT DISCRETE_INPUT_NDISCRETES;
+ USHORT usDiscreteInputStart;
+ iNReg = usNDiscrete / 8 + 1;
+
+ pucDiscreteInputBuf = ucSDiscInBuf;
+ DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
+ DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
+ usDiscreteInputStart = usSDiscInStart;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= DISCRETE_INPUT_START)
+ && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
+ {
+ iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
+ iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
+
+ while (iNReg > 0)
+ {
+ *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
+ iRegBitIndex, 8);
+ iNReg--;
+ }
+ pucRegBuffer--;
+ /* last discrete */
+ usNDiscrete = usNDiscrete % 8;
+ /* filling zero to high bit */
+ *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete);
+ *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete);
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+
+ return eStatus;
+}
+
diff --git a/components/net/freemodbus/port/user_mb_app.h b/components/net/freemodbus/port/user_mb_app.h
new file mode 100644
index 0000000000..864c3860bf
--- /dev/null
+++ b/components/net/freemodbus/port/user_mb_app.h
@@ -0,0 +1,46 @@
+#ifndef USER_APP
+#define USER_APP
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mb_m.h"
+#include "mbconfig.h"
+#include "mbframe.h"
+#include "mbutils.h"
+
+/* -----------------------Slave Defines -------------------------------------*/
+#define S_DISCRETE_INPUT_START 0
+#define S_DISCRETE_INPUT_NDISCRETES 16
+#define S_COIL_START 0
+#define S_COIL_NCOILS 64
+#define S_REG_INPUT_START 0
+#define S_REG_INPUT_NREGS 100
+#define S_REG_HOLDING_START 0
+#define S_REG_HOLDING_NREGS 100
+/* salve mode: holding register's all address */
+#define S_HD_RESERVE 0
+/* salve mode: input register's all address */
+#define S_IN_RESERVE 0
+/* salve mode: coil's all address */
+#define S_CO_RESERVE 0
+/* salve mode: discrete's all address */
+#define S_DI_RESERVE 0
+
+/* -----------------------Master Defines -------------------------------------*/
+#define M_DISCRETE_INPUT_START 0
+#define M_DISCRETE_INPUT_NDISCRETES 16
+#define M_COIL_START 0
+#define M_COIL_NCOILS 64
+#define M_REG_INPUT_START 0
+#define M_REG_INPUT_NREGS 100
+#define M_REG_HOLDING_START 0
+#define M_REG_HOLDING_NREGS 100
+/* master mode: holding register's all address */
+#define M_HD_RESERVE 0
+/* master mode: input register's all address */
+#define M_IN_RESERVE 0
+/* master mode: coil's all address */
+#define M_CO_RESERVE 0
+/* master mode: discrete's all address */
+#define M_DI_RESERVE 0
+
+#endif
diff --git a/components/net/freemodbus/port/user_mb_app_m.c b/components/net/freemodbus/port/user_mb_app_m.c
new file mode 100644
index 0000000000..12fabf21ac
--- /dev/null
+++ b/components/net/freemodbus/port/user_mb_app_m.c
@@ -0,0 +1,294 @@
+/*
+ * FreeModbus Libary: user callback functions and buffer define in master mode
+ * Copyright (C) 2013 Armink <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * File: $Id: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $
+ */
+#include "user_mb_app.h"
+
+/*-----------------------Master mode use these variables----------------------*/
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+//Master mode:DiscreteInputs variables
+USHORT usMDiscInStart = M_DISCRETE_INPUT_START;
+#if M_DISCRETE_INPUT_NDISCRETES%8
+UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
+#else
+UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
+#endif
+//Master mode:Coils variables
+USHORT usMCoilStart = M_COIL_START;
+#if M_COIL_NCOILS%8
+UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
+#else
+UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
+#endif
+//Master mode:InputRegister variables
+USHORT usMRegInStart = M_REG_INPUT_START;
+USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
+//Master mode:HoldingRegister variables
+USHORT usMRegHoldStart = M_REG_HOLDING_START;
+USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
+
+/**
+ * Modbus master input register callback function.
+ *
+ * @param pucRegBuffer input register buffer
+ * @param usAddress input register address
+ * @param usNRegs input register number
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex;
+ USHORT * pusRegInputBuf;
+ USHORT REG_INPUT_START;
+ USHORT REG_INPUT_NREGS;
+ USHORT usRegInStart;
+
+ pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1];
+ REG_INPUT_START = M_REG_INPUT_START;
+ REG_INPUT_NREGS = M_REG_INPUT_NREGS;
+ usRegInStart = usMRegInStart;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= REG_INPUT_START)
+ && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
+ {
+ iRegIndex = usAddress - usRegInStart;
+ while (usNRegs > 0)
+ {
+ pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
+ pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
+ iRegIndex++;
+ usNRegs--;
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+
+ return eStatus;
+}
+
+/**
+ * Modbus master holding register callback function.
+ *
+ * @param pucRegBuffer holding register buffer
+ * @param usAddress holding register address
+ * @param usNRegs holding register number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNRegs, eMBRegisterMode eMode)
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex;
+ USHORT * pusRegHoldingBuf;
+ USHORT REG_HOLDING_START;
+ USHORT REG_HOLDING_NREGS;
+ USHORT usRegHoldStart;
+
+ pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1];
+ REG_HOLDING_START = M_REG_HOLDING_START;
+ REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
+ usRegHoldStart = usMRegHoldStart;
+ /* if mode is read, the master will write the received date to buffer. */
+ eMode = MB_REG_WRITE;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= REG_HOLDING_START)
+ && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
+ {
+ iRegIndex = usAddress - usRegHoldStart;
+ switch (eMode)
+ {
+ /* read current register values from the protocol stack. */
+ case MB_REG_READ:
+ while (usNRegs > 0)
+ {
+ *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
+ *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
+ iRegIndex++;
+ usNRegs--;
+ }
+ break;
+ /* write current register values with new values from the protocol stack. */
+ case MB_REG_WRITE:
+ while (usNRegs > 0)
+ {
+ pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
+ pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
+ iRegIndex++;
+ usNRegs--;
+ }
+ break;
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+ return eStatus;
+}
+
+/**
+ * Modbus master coils callback function.
+ *
+ * @param pucRegBuffer coils buffer
+ * @param usAddress coils address
+ * @param usNCoils coils number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
+ USHORT usNCoils, eMBRegisterMode eMode)
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex , iRegBitIndex , iNReg;
+ UCHAR * pucCoilBuf;
+ USHORT COIL_START;
+ USHORT COIL_NCOILS;
+ USHORT usCoilStart;
+ iNReg = usNCoils / 8 + 1;
+
+ pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1];
+ COIL_START = M_COIL_START;
+ COIL_NCOILS = M_COIL_NCOILS;
+ usCoilStart = usMCoilStart;
+
+ /* if mode is read,the master will write the received date to buffer. */
+ eMode = MB_REG_WRITE;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= COIL_START)
+ && (usAddress + usNCoils <= COIL_START + COIL_NCOILS))
+ {
+ iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
+ iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
+ switch (eMode)
+ {
+ /* read current coil values from the protocol stack. */
+ case MB_REG_READ:
+ while (iNReg > 0)
+ {
+ *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
+ iRegBitIndex, 8);
+ iNReg--;
+ }
+ pucRegBuffer--;
+ /* last coils */
+ usNCoils = usNCoils % 8;
+ /* filling zero to high bit */
+ *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
+ *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
+ break;
+
+ /* write current coil values with new values from the protocol stack. */
+ case MB_REG_WRITE:
+ while (iNReg > 1)
+ {
+ xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
+ *pucRegBuffer++);
+ iNReg--;
+ }
+ /* last coils */
+ usNCoils = usNCoils % 8;
+ /* xMBUtilSetBits has bug when ucNBits is zero */
+ if (usNCoils != 0)
+ {
+ xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
+ *pucRegBuffer++);
+ }
+ break;
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+ return eStatus;
+}
+
+/**
+ * Modbus master discrete callback function.
+ *
+ * @param pucRegBuffer discrete buffer
+ * @param usAddress discrete address
+ * @param usNDiscrete discrete number
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
+{
+ eMBErrorCode eStatus = MB_ENOERR;
+ USHORT iRegIndex , iRegBitIndex , iNReg;
+ UCHAR * pucDiscreteInputBuf;
+ USHORT DISCRETE_INPUT_START;
+ USHORT DISCRETE_INPUT_NDISCRETES;
+ USHORT usDiscreteInputStart;
+ iNReg = usNDiscrete / 8 + 1;
+
+ pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1];
+ DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
+ DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
+ usDiscreteInputStart = usMDiscInStart;
+
+ /* it already plus one in modbus function method. */
+ usAddress--;
+
+ if ((usAddress >= DISCRETE_INPUT_START)
+ && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
+ {
+ iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
+ iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
+
+ /* write current discrete values with new values from the protocol stack. */
+ while (iNReg > 1)
+ {
+ xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8,
+ *pucRegBuffer++);
+ iNReg--;
+ }
+ /* last discrete */
+ usNDiscrete = usNDiscrete % 8;
+ /* xMBUtilSetBits has bug when ucNBits is zero */
+ if (usNDiscrete != 0)
+ {
+ xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
+ usNDiscrete, *pucRegBuffer++);
+ }
+ }
+ else
+ {
+ eStatus = MB_ENOREG;
+ }
+
+ return eStatus;
+}
+#endif
diff --git a/components/net/lwip-1.4.1/src/core/ipv4/ip.c b/components/net/lwip-1.4.1/src/core/ipv4/ip.c
index 95d2db404c..17bcd3929a 100644
--- a/components/net/lwip-1.4.1/src/core/ipv4/ip.c
+++ b/components/net/lwip-1.4.1/src/core/ipv4/ip.c
@@ -312,6 +312,11 @@ ip_input(struct pbuf *p, struct netif *inp)
int check_ip_src=1;
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
+#if IP_NAT
+ extern u8_t ip_nat_input(struct pbuf *p);
+ extern u8_t ip_nat_out(struct pbuf *p);
+#endif
+
IP_STATS_INC(ip.recv);
snmp_inc_ipinreceives();
@@ -487,15 +492,30 @@ ip_input(struct pbuf *p, struct netif *inp)
/* packet not for us? */
if (netif == NULL) {
+#if IP_FORWARD || IP_NAT
+ u8_t taken = 0;
+#endif /* IP_FORWARD || IP_NAT */
/* packet not for us, route or discard */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
-#if IP_FORWARD
+#if IP_FORWARD || IP_NAT
/* non-broadcast packet? */
- if (!ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
- /* try to forward IP packet on (other) interfaces */
- ip_forward(p, iphdr, inp);
- } else
+ if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
+#if IP_NAT
+ /* check if we want to perform NAT with this packet. */
+ taken = ip_nat_out(p);
+ if (!taken)
+#endif /* IP_NAT */
+ {
+#if IP_FORWARD
+ /* try to forward IP packet on (other) interfaces */
+ if (ip_forward(p, iphdr, inp) != NULL) {
+ taken = 1;
+ }
#endif /* IP_FORWARD */
+ }
+ }
+ if (!taken)
+#endif /* IP_FORWARD || IP_NAT */
{
snmp_inc_ipinaddrerrors();
snmp_inc_ipindiscards();
@@ -553,6 +573,13 @@ ip_input(struct pbuf *p, struct netif *inp)
current_netif = inp;
current_header = iphdr;
+#if IP_NAT
+ if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
+ (ip_nat_input(p) != 0)) {
+ LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet consumed by nat layer\n"));
+ } else
+#endif /* IP_NAT */
+
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0)
diff --git a/components/net/lwip-1.4.1/src/lwipopts.h b/components/net/lwip-1.4.1/src/lwipopts.h
index bff172e280..cb7def8ae6 100644
--- a/components/net/lwip-1.4.1/src/lwipopts.h
+++ b/components/net/lwip-1.4.1/src/lwipopts.h
@@ -161,6 +161,12 @@
*/
#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0)
+#ifdef LWIP_USING_NAT
+#define IP_NAT 1
+#else
+#define IP_NAT 0
+#endif
+
/* ---------- TCP options ---------- */
#ifdef RT_LWIP_TCP
#define LWIP_TCP 1
diff --git a/components/net/lwip_dhcpd/SConscript b/components/net/lwip_dhcpd/SConscript
new file mode 100644
index 0000000000..d5704c8c8b
--- /dev/null
+++ b/components/net/lwip_dhcpd/SConscript
@@ -0,0 +1,10 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('LwIP', src, depend = ['RT_USING_LWIP', 'LWIP_USING_DHCPD'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/net/lwip_dhcpd/dhcp_server.c b/components/net/lwip_dhcpd/dhcp_server.c
new file mode 100644
index 0000000000..47547a598b
--- /dev/null
+++ b/components/net/lwip_dhcpd/dhcp_server.c
@@ -0,0 +1,398 @@
+/*
+ * File : dhcp_server.c
+ * A simple DHCP server implementation
+ *
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ * http://www.rt-thread.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-01-30 aozima the first version
+ * 2013-08-08 aozima support different network segments.
+ * 2015-01-30 bernard release to RT-Thread RTOS.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <rtthread.h>
+
+#include <lwip/opt.h>
+#include <lwip/sockets.h>
+#include <lwip/inet_chksum.h>
+#include <netif/etharp.h>
+#include <netif/ethernetif.h>
+#include <lwip/ip.h>
+
+/* DHCP server option */
+
+/* allocated client ip range */
+#ifndef DHCPD_CLIENT_IP_MIN
+#define DHCPD_CLIENT_IP_MIN 2
+#endif
+#ifndef DHCPD_CLIENT_IP_MAX
+#define DHCPD_CLIENT_IP_MAX 254
+#endif
+
+/* the DHCP server address */
+#ifndef DHCPD_SERVER_IPADDR0
+#define DHCPD_SERVER_IPADDR0 192UL
+#define DHCPD_SERVER_IPADDR1 168UL
+#define DHCPD_SERVER_IPADDR2 169UL
+#define DHCPD_SERVER_IPADDR3 1UL
+#endif
+
+//#define DHCP_DEBUG_PRINTF
+
+#ifdef DHCP_DEBUG_PRINTF
+#define DEBUG_PRINTF rt_kprintf("[DHCP] "); rt_kprintf
+#else
+#define DEBUG_PRINTF(...)
+#endif /* DHCP_DEBUG_PRINTF */
+
+/* we need some routines in the DHCP of lwIP */
+#undef LWIP_DHCP
+#define LWIP_DHCP 1
+#include <lwip/dhcp.h>
+
+/* buffer size for receive DHCP packet */
+#define BUFSZ 1024
+
+static uint8_t next_client_ip = DHCPD_CLIENT_IP_MIN;
+static rt_err_t _low_level_dhcp_send(struct netif *netif,
+ const void *buffer,
+ rt_size_t size)
+{
+ struct pbuf *p;
+ struct eth_hdr *ethhdr;
+ struct ip_hdr *iphdr;
+ struct udp_hdr *udphdr;
+
+ p = pbuf_alloc(PBUF_LINK,
+ SIZEOF_ETH_HDR + sizeof(struct ip_hdr)
+ + sizeof(struct udp_hdr) + size,
+ PBUF_RAM);
+ if (p == RT_NULL) return -RT_ENOMEM;
+
+ ethhdr = (struct eth_hdr *)p->payload;
+ iphdr = (struct ip_hdr *)((char *)ethhdr + SIZEOF_ETH_HDR);
+ udphdr = (struct udp_hdr *)((char *)iphdr + sizeof(struct ip_hdr));
+
+ ETHADDR32_COPY(&ethhdr->dest, (struct eth_addr *)&ethbroadcast);
+ ETHADDR16_COPY(&ethhdr->src, netif->hwaddr);
+ ethhdr->type = PP_HTONS(ETHTYPE_IP);
+
+ iphdr->src.addr = 0x00000000; /* src: 0.0.0.0 */
+ iphdr->dest.addr = 0xFFFFFFFF; /* src: 255.255.255.255 */
+
+ IPH_VHL_SET(iphdr, 4, IP_HLEN / 4);
+ IPH_TOS_SET(iphdr, 0x00);
+ IPH_LEN_SET(iphdr, htons(IP_HLEN + sizeof(struct udp_hdr) + size));
+ IPH_ID_SET(iphdr, htons(2));
+ IPH_OFFSET_SET(iphdr, 0);
+ IPH_TTL_SET(iphdr, 255);
+ IPH_PROTO_SET(iphdr, IP_PROTO_UDP);
+ IPH_CHKSUM_SET(iphdr, 0);
+ IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
+
+ udphdr->src = htons(DHCP_SERVER_PORT);
+ udphdr->dest = htons(DHCP_CLIENT_PORT);
+ udphdr->len = htons(sizeof(struct udp_hdr) + size);
+ udphdr->chksum = 0;
+
+ memcpy((char *)udphdr + sizeof(struct udp_hdr),
+ buffer, size);
+
+ return netif->linkoutput(netif, p);
+}
+
+static void dhcpd_thread_entry(void *parameter)
+{
+ struct netif *netif = RT_NULL;
+ int sock;
+ int bytes_read;
+ char *recv_data;
+ rt_uint32_t addr_len;
+ struct sockaddr_in server_addr, client_addr;
+ struct dhcp_msg *msg;
+ int optval = 1;
+
+ /* get ethernet interface. */
+ netif = (struct netif*) parameter;
+ RT_ASSERT(netif != RT_NULL);
+
+ /* our DHCP server information */
+ DEBUG_PRINTF("DHCP server IP: %d.%d.%d.%d client IP: %d.%d.%d.%d-%d\n",
+ DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1,
+ DHCPD_SERVER_IPADDR2, DHCPD_SERVER_IPADDR3,
+ DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1,
+ DHCPD_SERVER_IPADDR2, DHCPD_CLIENT_IP_MIN, DHCPD_CLIENT_IP_MAX);
+
+ /* allocate buffer for receive */
+ recv_data = rt_malloc(BUFSZ);
+ if (recv_data == RT_NULL)
+ {
+ /* No memory */
+ DEBUG_PRINTF("Out of memory\n");
+ return;
+ }
+
+ /* create a socket with UDP */
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ {
+ DEBUG_PRINTF("create socket failed, errno = %d\n", errno);
+ rt_free(recv_data);
+ return;
+ }
+
+ /* set to receive broadcast packet */
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
+
+ /* initialize server address */
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(DHCP_SERVER_PORT);
+ server_addr.sin_addr.s_addr = INADDR_ANY;
+ rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
+
+ /* bind socket to the server address */
+ if (bind(sock, (struct sockaddr *)&server_addr,
+ sizeof(struct sockaddr)) == -1)
+ {
+ /* bind failed. */
+ DEBUG_PRINTF("bind server address failed, errno=%d\n", errno);
+ rt_free(recv_data);
+ return;
+ }
+
+ addr_len = sizeof(struct sockaddr);
+ DEBUG_PRINTF("DHCP server listen on port %d...\n", DHCP_SERVER_PORT);
+
+ while (1)
+ {
+ bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
+ (struct sockaddr *)&client_addr, &addr_len);
+ if (bytes_read < DHCP_MSG_LEN)
+ {
+ DEBUG_PRINTF("packet too short, wait for next!\n");
+ continue;
+ }
+
+ msg = (struct dhcp_msg *)recv_data;
+ /* check message type to make sure we can handle it */
+ if ((msg->op != DHCP_BOOTREQUEST) || (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE)))
+ {
+ continue;
+ }
+
+ /* handler. */
+ {
+ uint8_t *dhcp_opt;
+ uint8_t option;
+ uint8_t length;
+
+ uint8_t message_type = 0;
+ uint8_t finished = 0;
+ uint32_t request_ip = 0;
+
+ dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS;
+ while (finished == 0)
+ {
+ option = *dhcp_opt;
+ length = *(dhcp_opt + 1);
+
+ switch (option)
+ {
+ case DHCP_OPTION_REQUESTED_IP:
+ request_ip = *(dhcp_opt + 2) << 24 | *(dhcp_opt + 3) << 16
+ | *(dhcp_opt + 4) << 8 | *(dhcp_opt + 5);
+ break;
+
+ case DHCP_OPTION_END:
+ finished = 1;
+ break;
+
+ case DHCP_OPTION_MESSAGE_TYPE:
+ message_type = *(dhcp_opt + 2);
+ break;
+
+ default:
+ break;
+ } /* switch(option) */
+
+ dhcp_opt += (2 + length);
+ }
+
+ /* reply. */
+ dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS;
+
+ /* check. */
+ if (request_ip)
+ {
+ uint32_t client_ip = DHCPD_SERVER_IPADDR0 << 24 | DHCPD_SERVER_IPADDR1 << 16
+ | DHCPD_SERVER_IPADDR2 << 8 | (next_client_ip);
+
+ if (request_ip != client_ip)
+ {
+ *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE;
+ *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN;
+ *dhcp_opt++ = DHCP_NAK;
+ *dhcp_opt++ = DHCP_OPTION_END;
+
+ DEBUG_PRINTF("requested IP invalid, reply DHCP_NAK\n");
+ if (netif != RT_NULL)
+ {
+ int send_byte = (dhcp_opt - (uint8_t *)msg);
+ _low_level_dhcp_send(netif, msg, send_byte);
+ DEBUG_PRINTF("DHCP server send %d byte\n", send_byte);
+ }
+ next_client_ip++;
+ if (next_client_ip > DHCPD_CLIENT_IP_MAX)
+ next_client_ip = DHCPD_CLIENT_IP_MIN;
+ continue;
+ }
+ }
+
+ if (message_type == DHCP_DISCOVER)
+ {
+ DEBUG_PRINTF("request DHCP_DISCOVER\n");
+ DEBUG_PRINTF("reply DHCP_OFFER\n");
+
+ // DHCP_OPTION_MESSAGE_TYPE
+ *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE;
+ *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN;
+ *dhcp_opt++ = DHCP_OFFER;
+
+ // DHCP_OPTION_SERVER_ID
+ *dhcp_opt++ = DHCP_OPTION_SERVER_ID;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR0;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR1;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR2;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR3;
+
+ // DHCP_OPTION_LEASE_TIME
+ *dhcp_opt++ = DHCP_OPTION_LEASE_TIME;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = 0x00;
+ *dhcp_opt++ = 0x01;
+ *dhcp_opt++ = 0x51;
+ *dhcp_opt++ = 0x80;
+ }
+ else if (message_type == DHCP_REQUEST)
+ {
+ DEBUG_PRINTF("request DHCP_REQUEST\n");
+ DEBUG_PRINTF("reply DHCP_ACK\n");
+
+ // DHCP_OPTION_MESSAGE_TYPE
+ *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE;
+ *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN;
+ *dhcp_opt++ = DHCP_ACK;
+
+ // DHCP_OPTION_SERVER_ID
+ *dhcp_opt++ = DHCP_OPTION_SERVER_ID;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR0;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR1;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR2;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR3;
+
+ // DHCP_OPTION_SUBNET_MASK
+ *dhcp_opt++ = DHCP_OPTION_SUBNET_MASK;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = 0xFF;
+ *dhcp_opt++ = 0xFF;
+ *dhcp_opt++ = 0xFF;
+ *dhcp_opt++ = 0x00;
+
+#ifdef DHCPD_USING_ROUTER
+ // DHCP_OPTION_ROUTER
+ *dhcp_opt++ = DHCP_OPTION_ROUTER;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR0;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR1;
+ *dhcp_opt++ = DHCPD_SERVER_IPADDR2;
+ *dhcp_opt++ = 1;
+#endif
+
+ // DHCP_OPTION_DNS_SERVER, use the default DNS server address in lwIP
+ *dhcp_opt++ = DHCP_OPTION_DNS_SERVER;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = 208;
+ *dhcp_opt++ = 67;
+ *dhcp_opt++ = 222;
+ *dhcp_opt++ = 222;
+
+ // DHCP_OPTION_LEASE_TIME
+ *dhcp_opt++ = DHCP_OPTION_LEASE_TIME;
+ *dhcp_opt++ = 4;
+ *dhcp_opt++ = 0x00;
+ *dhcp_opt++ = 0x01;
+ *dhcp_opt++ = 0x51;
+ *dhcp_opt++ = 0x80;
+ }
+ else
+ {
+ DEBUG_PRINTF("un handle message:%d\n", message_type);
+ }
+
+ // append DHCP_OPTION_END
+ *dhcp_opt++ = DHCP_OPTION_END;
+
+ /* send reply. */
+ if ((message_type == DHCP_DISCOVER) || (message_type == DHCP_REQUEST))
+ {
+ msg->op = DHCP_BOOTREPLY;
+ IP4_ADDR(&msg->yiaddr,
+ DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1,
+ DHCPD_SERVER_IPADDR2, next_client_ip);
+
+ client_addr.sin_addr.s_addr = INADDR_BROADCAST;
+
+ if (netif != RT_NULL)
+ {
+ int send_byte = (dhcp_opt - (uint8_t *)msg);
+ _low_level_dhcp_send(netif, msg, send_byte);
+ DEBUG_PRINTF("DHCP server send %d byte\n", send_byte);
+ }
+ }
+ } /* handler. */
+ }
+}
+
+void dhcpd_start(char* netif_name)
+{
+ rt_thread_t thread;
+ struct netif *netif = RT_NULL;
+
+ /* find ethernet interface. */
+ netif = netif_find(netif_name);
+ if (netif == RT_NULL)
+ {
+ DEBUG_PRINTF("Not found network interface:%s\n", netif_name);
+ }
+
+ thread = rt_thread_create("dhcpd",
+ dhcpd_thread_entry, netif,
+ 1024,
+ RT_THREAD_PRIORITY_MAX - 3,
+ 2);
+ if (thread != RT_NULL)
+ {
+ rt_thread_startup(thread);
+ }
+}
+
diff --git a/components/net/lwip_dhcpd/dhcp_server.h b/components/net/lwip_dhcpd/dhcp_server.h
new file mode 100644
index 0000000000..4bd1163706
--- /dev/null
+++ b/components/net/lwip_dhcpd/dhcp_server.h
@@ -0,0 +1,36 @@
+/*
+ * File : dhcp_server.h
+ * A simple DHCP server implementation
+ *
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ * http://www.rt-thread.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-01-30 aozima the first version
+ * 2013-08-08 aozima support different network segments.
+ * 2015-01-30 bernard release to RT-Thread RTOS.
+ */
+
+#ifndef DHCPV4_SERVER_H__
+#define DHCPV4_SERVER_H__
+
+void dhcpd_start(char* netif_name);
+
+#endif
+
diff --git a/components/net/lwip_nat/README.md b/components/net/lwip_nat/README.md
new file mode 100644
index 0000000000..9672a11b54
--- /dev/null
+++ b/components/net/lwip_nat/README.md
@@ -0,0 +1,19 @@
+lwIP NAT componenent
+
+If you want to use lwIP NAT componenent, please define LWIP_USING_NAT in rtconfig.h.
+
+In this case the network 213.129.231.168/29 is nat'ed when packets are sent to the
+destination network 10.0.0.0/24 (untypical example - most users will have the other
+way around).
+
+Use following code to add a NAT entry:
+
+ ip_nat_entry_t nat_entry;
+
+ nat_entry.out_if = (struct netif *)&emac_if1;
+ nat_entry.in_if = (struct netif *)&emac_if2;
+ IP4_ADDR(&nat_entry.source_net, 213, 129, 231, 168);
+ IP4_ADDR(&nat_entry.source_netmask, 255, 255, 255, 248);
+ IP4_ADDR(&nat_entry.dest_net, 10, 0, 0, 0);
+ IP4_ADDR(&nat_entry.source_netmask, 255, 0, 0, 0);
+ ip_nat_add(&_nat_entry);
diff --git a/components/net/lwip_nat/SConscript b/components/net/lwip_nat/SConscript
new file mode 100644
index 0000000000..ce684f677a
--- /dev/null
+++ b/components/net/lwip_nat/SConscript
@@ -0,0 +1,10 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('LwIP', src, depend = ['RT_USING_LWIP', 'LWIP_USING_NAT'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/net/lwip_nat/ipv4_nat.c b/components/net/lwip_nat/ipv4_nat.c
new file mode 100644
index 0000000000..13c1877f2c
--- /dev/null
+++ b/components/net/lwip_nat/ipv4_nat.c
@@ -0,0 +1,1154 @@
+/**
+ * NAT - NAT implementation for lwIP supporting TCP/UDP and ICMP.
+ * Copyright (c) 2009 Christian Walter, ?Embedded Solutions, Vienna 2009.
+ *
+ * Copyright (c) 2010 lwIP project ;-)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ */
+
+/*
+ * File : ipv4_nat.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2015, RT-Thread Development Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2015-01-26 Hichard porting to RT-Thread
+ * 2015-01-27 Bernard code cleanup for lwIP in RT-Thread
+ */
+
+/*
+ * TODOS:
+ * - we should decide if we want to use static tables for NAT or a linked
+ * list.
+ * - we should allocate icmp ping id if multiple clients are sending
+ * ping requests.
+ * - maybe we could hash the identifiers for TCP, ICMP and UDP and use
+ * a single table structure. This would reduce the code amount although
+ * it will cost performance.
+ * - NAT code must check for broadcast addresses and NOT forward
+ * them.
+ *
+ * - netif_remove must notify NAT code when a NAT'ed interface is removed
+ * - allocate NAT entries from a new memp pool instead of the heap
+ * - let ttl be ticks, not seconds
+ *
+ * HOWTO USE:
+ *
+ * Shows how to create NAT between a PPP interface and an internal NIC.
+ * In this case the network 213.129.231.168/29 is nat'ed when packets
+ * are sent to the destination network 10.0.0.0/24 (untypical example -
+ * most users will have the other way around).
+ *
+ * Step 1) Execute when network interfaces are ready.
+ *
+ * new_nat_entry.out_if = (struct netif *)&PPP_IF;
+ * new_nat_entry.in_if = (struct netif *)&EMAC_if;
+ * IP4_ADDR(&new_nat_entry.source_net, 213, 129, 231, 168);
+ * IP4_ADDR(&new_nat_entry.source_netmask, 255, 255, 255, 248);
+ * IP4_ADDR(&new_nat_entry.dest_net, 10, 0, 0, 0);
+ * IP4_ADDR(&new_nat_entry.source_netmask, 255, 0, 0, 0);
+ * ip_nat_add(&new_nat_entry);
+ */
+
+#include "ipv4_nat.h"
+#include "lwip/opt.h"
+
+#ifdef LWIP_USING_NAT
+
+#include "lwip/ip.h"
+#include "lwip/inet.h"
+#include "lwip/netif.h"
+#include "lwip/ip_addr.h"
+#include "lwip/icmp.h"
+#include "lwip/tcp_impl.h"
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/sys.h"
+#include "lwip/timers.h"
+#include "netif/etharp.h"
+
+#include <limits.h>
+#include <string.h>
+
+/** Define this to enable debug output of this module */
+#ifndef LWIP_NAT_DEBUG
+#define LWIP_NAT_DEBUG LWIP_DBG_OFF
+#endif
+
+#define LWIP_NAT_TTL_INFINITE (INT_MAX)
+#define LWIP_NAT_DEFAULT_TTL_SECONDS (128)
+#define LWIP_NAT_FORWARD_HEADER_SIZE_MIN (sizeof(struct eth_hdr))
+
+#define LWIP_NAT_DEFAULT_STATE_TABLES_ICMP (4)
+#define LWIP_NAT_DEFAULT_STATE_TABLES_TCP (32)
+#define LWIP_NAT_DEFAULT_STATE_TABLES_UDP (32)
+
+#define LWIP_NAT_DEFAULT_TCP_SOURCE_PORT (40000)
+#define LWIP_NAT_DEFAULT_UDP_SOURCE_PORT (40000)
+
+#define IPNAT_ENTRY_RESET(x) do { \
+ (x)->ttl = 0; \
+} while(0)
+
+typedef struct ip_nat_conf
+{
+ struct ip_nat_conf *next;
+ ip_nat_entry_t entry;
+} ip_nat_conf_t;
+
+typedef struct ip_nat_entry_common
+{
+ s32_t ttl; /* @todo: do we really need this to be signed?? */
+ ip_addr_t source;
+ ip_addr_t dest;
+ ip_nat_conf_t *cfg;
+} ip_nat_entry_common_t;
+
+typedef struct ip_nat_entries_icmp
+{
+ ip_nat_entry_common_t common;
+ u16_t id;
+ u16_t seqno;
+} ip_nat_entries_icmp_t;
+
+typedef struct ip_nat_entries_tcp
+{
+ ip_nat_entry_common_t common;
+ u16_t nport;
+ u16_t sport;
+ u16_t dport;
+} ip_nat_entries_tcp_t;
+
+typedef struct ip_nat_entries_udp
+{
+ ip_nat_entry_common_t common;
+ u16_t nport;
+ u16_t sport;
+ u16_t dport;
+} ip_nat_entries_udp_t;
+
+typedef union u_nat_entry
+{
+ ip_nat_entry_common_t *cmn;
+ ip_nat_entries_tcp_t *tcp;
+ ip_nat_entries_icmp_t *icmp;
+ ip_nat_entries_udp_t *udp;
+} nat_entry_t;
+
+static ip_nat_conf_t *ip_nat_cfg = NULL;
+static ip_nat_entries_icmp_t ip_nat_icmp_table[LWIP_NAT_DEFAULT_STATE_TABLES_ICMP];
+static ip_nat_entries_tcp_t ip_nat_tcp_table[LWIP_NAT_DEFAULT_STATE_TABLES_TCP];
+static ip_nat_entries_udp_t ip_nat_udp_table[LWIP_NAT_DEFAULT_STATE_TABLES_UDP];
+
+/* ----------------------- Static functions (COMMON) --------------------*/
+static void ip_nat_chksum_adjust(u8_t *chksum, const u8_t *optr, s16_t olen, const u8_t *nptr, s16_t nlen);
+static void ip_nat_cmn_init(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr,
+ ip_nat_entry_common_t *nat_entry);
+static ip_nat_conf_t *ip_nat_shallnat(const struct ip_hdr *iphdr);
+static void ip_nat_reset_state(ip_nat_conf_t *cfg);
+
+/* ----------------------- Static functions (DEBUG) ---------------------*/
+#if defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON)
+static void ip_nat_dbg_dump(const char *msg, const struct ip_hdr *iphdr);
+static void ip_nat_dbg_dump_ip(const ip_addr_t *addr);
+static void ip_nat_dbg_dump_icmp_nat_entry(const char *msg, const ip_nat_entries_icmp_t *nat_entry);
+static void ip_nat_dbg_dump_tcp_nat_entry(const char *msg, const ip_nat_entries_tcp_t *nat_entry);
+static void ip_nat_dbg_dump_udp_nat_entry(const char *msg, const ip_nat_entries_udp_t *nat_entry);
+static void ip_nat_dbg_dump_init(ip_nat_conf_t *ip_nat_cfg_new);
+static void ip_nat_dbg_dump_remove(ip_nat_conf_t *cur);
+#else /* defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) */
+#define ip_nat_dbg_dump(msg, iphdr)
+#define ip_nat_dbg_dump_ip(addr)
+#define ip_nat_dbg_dump_icmp_nat_entry(msg, nat_entry)
+#define ip_nat_dbg_dump_tcp_nat_entry(msg, nat_entry)
+#define ip_nat_dbg_dump_udp_nat_entry(msg, nat_entry)
+#define ip_nat_dbg_dump_init(ip_nat_cfg_new)
+#define ip_nat_dbg_dump_remove(cur)
+#endif /* defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) */
+
+/* ----------------------- Static functions (TCP) -----------------------*/
+static ip_nat_entries_tcp_t *ip_nat_tcp_lookup_incoming(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr);
+static ip_nat_entries_tcp_t *ip_nat_tcp_lookup_outgoing(ip_nat_conf_t *nat_config,
+ const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr,
+ u8_t allocate);
+
+/* ----------------------- Static functions (UDP) -----------------------*/
+static ip_nat_entries_udp_t *ip_nat_udp_lookup_incoming(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr);
+static ip_nat_entries_udp_t *ip_nat_udp_lookup_outgoing(ip_nat_conf_t *nat_config,
+ const struct ip_hdr *iphdr, const struct udp_hdr *udphdr,
+ u8_t allocate);
+
+/**
+ * Timer callback function that calls ip_nat_tmr() and reschedules itself.
+ *
+ * @param arg unused argument
+ */
+static void
+nat_timer(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nat_timer()\n"));
+
+ ip_nat_tmr();
+ sys_timeout(LWIP_NAT_TMR_INTERVAL_SEC, nat_timer, NULL);
+}
+
+/** Initialize this module */
+void
+ip_nat_init(void)
+{
+ int i;
+ extern void lwip_ip_input_set_hook(int (*hook)(struct pbuf *p, struct netif *inp));
+
+ /* @todo: this can be omitted since we trust static variables
+ to be initialized to zero */
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) {
+ IPNAT_ENTRY_RESET(&ip_nat_icmp_table[i].common);
+ }
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) {
+ IPNAT_ENTRY_RESET(&ip_nat_tcp_table[i].common);
+ }
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) {
+ IPNAT_ENTRY_RESET(&ip_nat_udp_table[i].common);
+ }
+
+ /* we must lock scheduler to protect following code */
+ rt_enter_critical();
+
+ /* add a lwip timer for NAT */
+ sys_timeout(LWIP_NAT_TMR_INTERVAL_SEC, nat_timer, NULL);
+
+ /* un-protect */
+ rt_exit_critical();
+}
+
+/** Allocate a new ip_nat_conf_t item */
+static ip_nat_conf_t*
+ip_nat_alloc(void)
+{
+ ip_nat_conf_t *ret = (ip_nat_conf_t*)mem_malloc(sizeof(ip_nat_conf_t));
+ return ret;
+}
+
+/** Free a removed ip_nat_conf_t item */
+static void
+ip_nat_free(ip_nat_conf_t *item)
+{
+ LWIP_ASSERT("item != NULL", item != NULL);
+ mem_free(item);
+}
+
+/** Add a new NAT entry
+ *
+ * @param new_entry pointer to a structure used to initialize the entry
+ * @return ERR_OK if succeeded
+ */
+err_t
+ip_nat_add(const ip_nat_entry_t *new_entry)
+{
+ err_t err = ERR_VAL;
+ ip_nat_conf_t *cur = ip_nat_cfg;
+ ip_nat_conf_t *ip_nat_cfg_new = ip_nat_alloc();
+ LWIP_ASSERT("new_entry != NULL", new_entry != NULL);
+
+ if (ip_nat_cfg_new != NULL) {
+ SMEMCPY(&ip_nat_cfg_new->entry, new_entry, sizeof(ip_nat_entry_t));
+ ip_nat_cfg_new->next = NULL;
+
+ ip_nat_dbg_dump_init(ip_nat_cfg_new);
+
+ if (ip_nat_cfg == NULL) {
+ ip_nat_cfg = ip_nat_cfg_new;
+ } else {
+ /* @todo: do we really need to enqueue the new entry at the end?? */
+ while (cur->next != NULL) {
+ cur = cur->next;
+ }
+ cur->next = ip_nat_cfg_new;
+ }
+ err = ERR_OK;
+ } else {
+ err = ERR_MEM;
+ }
+ return err;
+}
+
+/** Remove a NAT entry previously added by 'ip_nat_add()'.
+ *
+ * @param remove_entry describes the entry to remove
+ */
+void
+ip_nat_remove(const ip_nat_entry_t *remove_entry)
+{
+ ip_nat_conf_t *cur = ip_nat_cfg;
+ ip_nat_conf_t *next;
+ ip_nat_conf_t *previous = NULL;
+
+ while (cur != NULL) {
+ /* Remove the NAT interfaces */
+ if ((cur->entry.source_net.addr == remove_entry->source_net.addr) &&
+ (cur->entry.source_netmask.addr == remove_entry->source_netmask.addr) &&
+ (cur->entry.dest_net.addr == remove_entry->dest_net.addr) &&
+ (cur->entry.dest_netmask.addr == remove_entry->dest_netmask.addr) &&
+ (cur->entry.out_if == remove_entry->out_if) &&
+ (cur->entry.in_if == remove_entry->in_if))
+ {
+ ip_nat_dbg_dump_remove(cur);
+
+ ip_nat_reset_state(cur);
+ next = cur->next;
+ if (cur == ip_nat_cfg) {
+ ip_nat_cfg = next;
+ } else {
+ LWIP_ASSERT("NULL != previous", NULL != previous);
+ previous->next = next;
+ }
+ /* free 'cur' or there will be a memory leak */
+ ip_nat_free(cur);
+ return;
+ } else {
+ previous = cur;
+ cur = cur->next;
+ }
+ }
+}
+
+/** Reset a NAT configured entry to be reused.
+ * Effectively calls IPNAT_ENTRY_RESET() on 'cfg'.
+ *
+ * @param cfg NAT entry to reset
+ */
+static void
+ip_nat_reset_state(ip_nat_conf_t *cfg)
+{
+ int i;
+
+ /* @todo: optimize this!!!
+ why do we search for it anyway, if we have the pointer??? */
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) {
+ if(ip_nat_icmp_table[i].common.cfg == cfg) {
+ IPNAT_ENTRY_RESET(&ip_nat_icmp_table[i].common);
+ }
+ }
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) {
+ if(ip_nat_icmp_table[i].common.cfg == cfg) {
+ IPNAT_ENTRY_RESET(&ip_nat_tcp_table[i].common);
+ }
+ }
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) {
+ if(ip_nat_icmp_table[i].common.cfg == cfg) {
+ IPNAT_ENTRY_RESET(&ip_nat_udp_table[i].common);
+ }
+ }
+}
+
+/** Check if this packet should be routed or should be translated
+ *
+ * @param iphdr the IP header to check
+ * @return - a NAT entry if the packet shall be translated,
+ * - NULL if the packet shall be routed normally
+ */
+static ip_nat_conf_t *
+ip_nat_shallnat(const struct ip_hdr *iphdr)
+{
+ ip_nat_conf_t *nat_config = ip_nat_cfg;
+
+ for (nat_config = ip_nat_cfg; nat_config != NULL; nat_config = nat_config->next) {
+ if (ip_addr_netcmp(&(iphdr->dest), &(nat_config->entry.dest_net),
+ &(nat_config->entry.dest_netmask)) ||
+ ip_addr_netcmp(&(iphdr->src), &(nat_config->entry.source_net),
+ &(nat_config->entry.source_netmask))) {
+ break;
+ }
+ }
+
+ return nat_config;
+}
+
+/** Check if the IP header can be hidden and if the remaining packet
+ * is long enough. p->payload is reset to the IP header on return.
+ *
+ * @param p received packet, p->payload pointing to IP header
+ * @param min_size minimum p->tot_len after hiding IP header
+ * @return a pointer to the next header (after IP header),
+ * NULL if hiding IP header fails or the packet is too short
+ */
+static void*
+ip_nat_check_header(struct pbuf *p, u16_t min_size)
+{
+ void *ret = NULL;
+ struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
+ s16_t iphdr_len = IPH_HL(iphdr) * 4;
+
+ if(!pbuf_header(p, -iphdr_len)) {
+ if(p->tot_len >= min_size) {
+ ret = p->payload;
+ }
+ /* Restore pbuf payload pointer from previous header check. */
+ pbuf_header(p, iphdr_len);
+ }
+ return ret;
+}
+
+/** Input processing: check if a received packet belongs to a NAT entry
+ * and if so, translated it and send it on.
+ *
+ * @param p received packet
+ * @return 1 if the packet has been consumed (it was a NAT packet),
+ * 0 if the packet has not been consumed (no NAT packet)
+ */
+u8_t
+ip_nat_input(struct pbuf *p)
+{
+ struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
+ struct tcp_hdr *tcphdr;
+ struct udp_hdr *udphdr;
+ struct icmp_echo_hdr *icmphdr;
+ nat_entry_t nat_entry;
+ err_t err;
+ u8_t consumed = 0;
+ int i;
+ struct pbuf *q = NULL;
+
+ nat_entry.cmn = NULL;
+ ip_nat_dbg_dump("ip_nat_in: checking nat for", iphdr);
+
+ switch (IPH_PROTO(iphdr)) {
+ case IP_PROTO_TCP:
+ tcphdr = (struct tcp_hdr*)ip_nat_check_header(p, sizeof(struct tcp_hdr));
+ if (tcphdr == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: short tcp packet (%" U16_F " bytes) discarded\n", p->tot_len));
+ } else {
+ nat_entry.tcp = ip_nat_tcp_lookup_incoming(iphdr, tcphdr);
+ if (nat_entry.tcp != NULL) {
+ /* Refresh TCP entry */
+ nat_entry.tcp->common.ttl = LWIP_NAT_DEFAULT_TTL_SECONDS;
+ tcphdr->dest = nat_entry.tcp->sport;
+ /* Adjust TCP checksum for changed destination port */
+ ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum),
+ (u8_t *)&(nat_entry.tcp->nport), 2, (u8_t *)&(tcphdr->dest), 2);
+ /* Adjust TCP checksum for changing dest IP address */
+ ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum),
+ (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4,
+ (u8_t *)&(nat_entry.cmn->source.addr), 4);
+
+ consumed = 1;
+ }
+ }
+ break;
+
+ case IP_PROTO_UDP:
+ udphdr = (struct udp_hdr *)ip_nat_check_header(p, sizeof(struct udp_hdr));
+ if (udphdr == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_input: short udp packet (%" U16_F " bytes) discarded\n",
+ p->tot_len));
+ } else {
+ nat_entry.udp = ip_nat_udp_lookup_incoming(iphdr, udphdr);
+ if (nat_entry.udp != NULL) {
+ /* Refresh UDP entry */
+ nat_entry.udp->common.ttl = LWIP_NAT_DEFAULT_TTL_SECONDS;
+ udphdr->dest = nat_entry.udp->sport;
+ /* Adjust UDP checksum for changed destination port */
+ ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum),
+ (u8_t *)&(nat_entry.udp->nport), 2, (u8_t *)&(udphdr->dest), 2);
+ /* Adjust UDP checksum for changing dest IP address */
+ ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum),
+ (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4,
+ (u8_t *)&(nat_entry.cmn->source.addr), 4);
+
+ consumed = 1;
+ }
+ }
+ break;
+
+ case IP_PROTO_ICMP:
+ icmphdr = (struct icmp_echo_hdr *)ip_nat_check_header(p, sizeof(struct icmp_echo_hdr));
+ if (icmphdr == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_out: short icmp echo reply packet (%" U16_F " bytes) discarded\n",
+ p->tot_len));
+ } else {
+ if (ICMP_ER == ICMPH_TYPE(icmphdr)) {
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) {
+ nat_entry.icmp = &ip_nat_icmp_table[i];
+ if ((nat_entry.icmp->common.ttl) &&
+ (iphdr->src.addr == nat_entry.icmp->common.dest.addr) &&
+ (nat_entry.icmp->id == icmphdr->id) &&
+ (nat_entry.icmp->seqno == icmphdr->seqno)) {
+ ip_nat_dbg_dump_icmp_nat_entry("found existing nat entry: ", nat_entry.icmp);
+ consumed = 1;
+ IPNAT_ENTRY_RESET(nat_entry.cmn);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if(consumed) {
+ /* packet consumed, send it out on in_if */
+ struct netif *in_if;
+
+ /* check if the pbuf has room for link headers */
+ if (pbuf_header(p, PBUF_LINK_HLEN)) {
+ /* pbuf has no room for link headers, allocate an extra pbuf */
+ q = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
+ if (q == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: no pbuf for outgoing header\n"));
+ // rt_kprintf("ip_nat_input: no pbuf for outgoing header\n");
+ /* @todo: stats? */
+ pbuf_free(p);
+ p = NULL;
+ return 1;
+ } else {
+ pbuf_cat(q, p);
+ }
+ } else {
+ /* restore p->payload to IP header */
+ if (pbuf_header(p, -PBUF_LINK_HLEN)) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: restoring header failed\n"));
+ // rt_kprintf("ip_nat_input: restoring header failed\n");
+ /* @todo: stats? */
+ pbuf_free(p);
+ p = NULL;
+ return 1;
+ }
+ else q = p;
+ }
+ /* if we come here, q is the pbuf to send (either points to p or to a chain) */
+ in_if = nat_entry.cmn->cfg->entry.in_if;
+ iphdr->dest.addr = nat_entry.cmn->source.addr;
+ ip_nat_chksum_adjust((u8_t *) & IPH_CHKSUM(iphdr),
+ (u8_t *) & (nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4,
+ (u8_t *) & (iphdr->dest.addr), 4);
+
+ ip_nat_dbg_dump("ip_nat_input: packet back to source after nat: ", iphdr);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: sending packet on interface ("));
+ ip_nat_dbg_dump_ip(&(in_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n"));
+
+ err = in_if->output(in_if, q, (ip_addr_t *)&(iphdr->dest));
+ if(err != ERR_OK) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_input: failed to send rewritten packet. link layer returned %d\n",
+ err));
+ // rt_kprintf("ip_nat_input: failed to send rewritten packet. link layer returned %d\n", err);
+ }
+ /* now that q (and/or p) is sent (or not), give up the reference to it
+ this frees the input pbuf (p) as we have consumed it. */
+ pbuf_free(q);
+ }
+ return consumed;
+}
+
+/** Check if one NAT entry timed out */
+static void
+ip_nat_check_timeout(ip_nat_entry_common_t *nat_entry)
+{
+ if(nat_entry->ttl > 0) {
+ if(nat_entry->ttl != LWIP_NAT_TTL_INFINITE) {
+ /* this is not a 'no-timeout' entry */
+ if(nat_entry->ttl > LWIP_NAT_TMR_INTERVAL_SEC) {
+ nat_entry->ttl -= LWIP_NAT_TMR_INTERVAL_SEC;
+ } else {
+ nat_entry->ttl = 0;
+ }
+ }
+ }
+}
+
+/** The NAT timer function, to be called at an interval of
+ * LWIP_NAT_TMR_INTERVAL_SEC seconds.
+ */
+void
+ip_nat_tmr(void)
+{
+ int i;
+
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_tmr: removing old entries\n"));
+
+ for(i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) {
+ ip_nat_check_timeout((ip_nat_entry_common_t *) & ip_nat_icmp_table[i]);
+ }
+ for(i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) {
+ ip_nat_check_timeout((ip_nat_entry_common_t *) & ip_nat_tcp_table[i]);
+ }
+ for(i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) {
+ ip_nat_check_timeout((ip_nat_entry_common_t *) & ip_nat_udp_table[i]);
+ }
+}
+
+/** Vheck if we want to perform NAT with this packet. If so, send it out on
+ * the correct interface.
+ *
+ * @param p the packet to test/send
+ * @return 1: the packet has been sent using NAT,
+ * 0: the packet did not belong to a NAT entry
+ */
+u8_t
+ip_nat_out(struct pbuf *p)
+{
+ u8_t sent = 0;
+ err_t err;
+ struct ip_hdr *iphdr = p->payload;
+ struct icmp_echo_hdr *icmphdr;
+ struct tcp_hdr *tcphdr;
+ struct udp_hdr *udphdr;
+ ip_nat_conf_t *nat_config;
+ nat_entry_t nat_entry;
+ int i;
+
+ nat_entry.cmn = NULL;
+
+ ip_nat_dbg_dump("ip_nat_out: checking nat for", iphdr);
+
+ /* Check if this packet should be routed or should be translated */
+ nat_config = ip_nat_shallnat(iphdr);
+ if (nat_config != NULL ) {
+ if (nat_config->entry.out_if == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: no external interface for nat table entry\n"));
+ } else {
+ switch (IPH_PROTO(iphdr))
+ {
+ case IP_PROTO_TCP:
+ tcphdr = (struct tcp_hdr *)ip_nat_check_header(p, sizeof(struct tcp_hdr));
+ if (tcphdr == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_out: short tcp packet (%" U16_F " bytes) discarded\n", p->tot_len));
+ } else {
+ nat_entry.tcp = ip_nat_tcp_lookup_outgoing(nat_config, iphdr, tcphdr, 1);
+ if (nat_entry.tcp != NULL) {
+ /* Adjust TCP checksum for changing source port */
+ tcphdr->src = nat_entry.tcp->nport;
+ ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum),
+ (u8_t *)&(nat_entry.tcp->sport), 2, (u8_t *)&(tcphdr->src), 2);
+ /* Adjust TCP checksum for changing source IP address */
+ ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum),
+ (u8_t *)&(nat_entry.cmn->source.addr), 4,
+ (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4);
+ }
+ }
+ break;
+
+ case IP_PROTO_UDP:
+ udphdr = (struct udp_hdr *)ip_nat_check_header(p, sizeof(struct udp_hdr));
+ if (udphdr == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_out: short udp packet (%" U16_F " bytes) discarded\n", p->tot_len));
+ } else {
+ nat_entry.udp = ip_nat_udp_lookup_outgoing(nat_config, iphdr, udphdr, 1);
+ if (nat_entry.udp != NULL) {
+ /* Adjust UDP checksum for changing source port */
+ udphdr->src = nat_entry.udp->nport;
+ ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum),
+ (u8_t *)&(nat_entry.udp->sport), 2, (u8_t *) & (udphdr->src), 2);
+ /* Adjust UDP checksum for changing source IP address */
+ ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum),
+ (u8_t *)&(nat_entry.cmn->source.addr), 4,
+ (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4);
+ }
+ }
+ break;
+
+ case IP_PROTO_ICMP:
+ icmphdr = (struct icmp_echo_hdr *)ip_nat_check_header(p, sizeof(struct icmp_echo_hdr));
+ if(icmphdr == NULL) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_out: short icmp echo packet (%" U16_F " bytes) discarded\n", p->tot_len));
+ } else {
+ if (ICMPH_TYPE(icmphdr) == ICMP_ECHO) {
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) {
+ if (!ip_nat_icmp_table[i].common.ttl) {
+ nat_entry.icmp = &ip_nat_icmp_table[i];
+ ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);
+ nat_entry.icmp->id = icmphdr->id;
+ nat_entry.icmp->seqno = icmphdr->seqno;
+ ip_nat_dbg_dump_icmp_nat_entry(" ip_nat_out: created new NAT entry ", nat_entry.icmp);
+ break;
+ }
+ }
+ if (NULL == nat_entry.icmp)
+ {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: no more NAT entries for ICMP available\n"));
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (nat_entry.cmn != NULL) {
+ struct netif *out_if = nat_entry.cmn->cfg->entry.out_if;
+ /* Exchange the IP source address with the address of the interface
+ * where the packet will be sent.
+ */
+ /* @todo: check nat_config->entry.out_if agains nat_entry.cmn->cfg->entry.out_if */
+ iphdr->src.addr = nat_config->entry.out_if->ip_addr.addr;
+ ip_nat_chksum_adjust((u8_t *) & IPH_CHKSUM(iphdr),
+ (u8_t *) & (nat_entry.cmn->source.addr), 4, (u8_t *) & iphdr->src.addr, 4);
+
+ ip_nat_dbg_dump("ip_nat_out: rewritten packet", iphdr);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: sending packet on interface ("));
+ ip_nat_dbg_dump_ip(&(out_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n"));
+
+ err = out_if->output(out_if, p, (ip_addr_t *)&(iphdr->dest));
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG,
+ ("ip_nat_out: failed to send rewritten packet. link layer returned %d\n", err));
+ // rt_kprintf("ip_nat_out: failed to send rewritten packet. link layer returned %d\n", err);
+ } else {
+ sent = 1;
+ }
+ }
+ }
+ }
+
+ return sent;
+}
+
+/** Initialize common parts of a NAT entry
+ *
+ * @param nat_config NAT config entry
+ * @param iphdr IP header from which to initialize the entry
+ * @param nat_entry entry to initialize
+ */
+static void
+ip_nat_cmn_init(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr, ip_nat_entry_common_t *nat_entry)
+{
+ LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry);
+ LWIP_ASSERT("NULL != nat_config", NULL != nat_config);
+ LWIP_ASSERT("NULL != iphdr", NULL != iphdr);
+ nat_entry->cfg = nat_config;
+ nat_entry->dest = *((ip_addr_t *)&iphdr->dest);
+ nat_entry->source = *((ip_addr_t *)&iphdr->src);
+ nat_entry->ttl = LWIP_NAT_DEFAULT_TTL_SECONDS;
+}
+
+/**
+ * This function checks for incoming packets if we already have a NAT entry.
+ * If yes a pointer to the NAT entry is returned. Otherwise NULL.
+ *
+ * @param nat_config NAT configuration.
+ * @param iphdr The IP header.
+ * @param udphdr The UDP header.
+ * @return A pointer to an existing NAT entry or
+ * NULL if none is found.
+ */
+static ip_nat_entries_udp_t *
+ip_nat_udp_lookup_incoming(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr)
+{
+ int i;
+ ip_nat_entries_udp_t *nat_entry = NULL;
+
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) {
+ if (ip_nat_udp_table[i].common.ttl) {
+ if ((iphdr->src.addr == ip_nat_udp_table[i].common.dest.addr) &&
+ (udphdr->src == ip_nat_udp_table[i].dport) &&
+ (udphdr->dest == ip_nat_udp_table[i].nport)) {
+ nat_entry = &ip_nat_udp_table[i];
+ ip_nat_dbg_dump_udp_nat_entry("ip_nat_udp_lookup_incoming: found existing nat entry: ",
+ nat_entry);
+ break;
+ }
+ }
+ }
+ return nat_entry;
+}
+
+/**
+ * This function checks if we already have a NAT entry for this UDP connection.
+ * If yes the a pointer to this NAT entry is returned.
+ *
+ * @param iphdr The IP header.
+ * @param udphdr The UDP header.
+ * @param allocate If no existing NAT entry is found and this flag is true
+ * a NAT entry is allocated.
+ */
+static ip_nat_entries_udp_t *
+ip_nat_udp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr,
+ const struct udp_hdr *udphdr, u8_t allocate)
+{
+ int i;
+ nat_entry_t nat_entry;
+ int last_free = -1;
+
+ nat_entry.cmn = NULL;
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) {
+ if (ip_nat_udp_table[i].common.ttl) {
+ if ((iphdr->src.addr == ip_nat_udp_table[i].common.source.addr) &&
+ (iphdr->dest.addr == ip_nat_udp_table[i].common.dest.addr) &&
+ (udphdr->src == ip_nat_udp_table[i].sport) &&
+ (udphdr->dest == ip_nat_udp_table[i].dport)) {
+ nat_entry.udp = &ip_nat_udp_table[i];
+
+ ip_nat_dbg_dump_udp_nat_entry("ip_nat_udp_lookup_outgoing: found existing nat entry: ",
+ nat_entry.udp);
+ break;
+ }
+ } else {
+ last_free = i;
+ }
+ }
+ if (nat_entry.cmn == NULL) {
+ if (allocate) {
+ if (last_free != -1) {
+ nat_entry.udp = &ip_nat_udp_table[last_free];
+ nat_entry.udp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_UDP_SOURCE_PORT + i));
+ nat_entry.udp->sport = udphdr->src;
+ nat_entry.udp->dport = udphdr->dest;
+ ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);
+
+ ip_nat_dbg_dump_udp_nat_entry("ip_nat_udp_lookup_outgoing: created new nat entry: ",
+ nat_entry.udp);
+ } else {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_udp_lookup_outgoing: no more NAT entries available\n"));
+ // rt_kprintf("ip_nat_udp_lookup_outgoing: no more NAT entries available\n");
+ }
+ }
+ }
+ return nat_entry.udp;
+}
+
+/**
+ * This function checks for incoming packets if we already have a NAT entry.
+ * If yes a pointer to the NAT entry is returned. Otherwise NULL.
+ *
+ * @param nat_config NAT configuration.
+ * @param iphdr The IP header.
+ * @param tcphdr The TCP header.
+ * @return A pointer to an existing NAT entry or NULL if none is found.
+ */
+static ip_nat_entries_tcp_t *
+ip_nat_tcp_lookup_incoming(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr)
+{
+ int i;
+ ip_nat_entries_tcp_t *nat_entry = NULL;
+
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) {
+ if (ip_nat_tcp_table[i].common.ttl) {
+ if ((iphdr->src.addr == ip_nat_tcp_table[i].common.dest.addr) &&
+ (tcphdr->src == ip_nat_tcp_table[i].dport) &&
+ (tcphdr->dest == ip_nat_tcp_table[i].nport)) {
+ nat_entry = &ip_nat_tcp_table[i];
+
+ ip_nat_dbg_dump_tcp_nat_entry("ip_nat_tcp_lookup_incoming: found existing nat entry: ",
+ nat_entry);
+ break;
+ }
+ }
+ }
+ return nat_entry;
+}
+
+/**
+ * This function checks if we already have a NAT entry for this TCP connection.
+ * If yes the a pointer to this NAT entry is returned.
+ *
+ * @param iphdr The IP header.
+ * @param tcphdr The TCP header.
+ * @param allocate If no existing NAT entry is found and this flag is true
+ * a NAT entry is allocated.
+ */
+static ip_nat_entries_tcp_t *
+ip_nat_tcp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr,
+ const struct tcp_hdr *tcphdr, u8_t allocate)
+{
+ int i;
+ nat_entry_t nat_entry;
+ int last_free = -1;
+
+ nat_entry.cmn = NULL;
+ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) {
+ if (ip_nat_tcp_table[i].common.ttl) {
+ if ((iphdr->src.addr == ip_nat_tcp_table[i].common.source.addr) &&
+ (iphdr->dest.addr == ip_nat_tcp_table[i].common.dest.addr) &&
+ (tcphdr->src == ip_nat_tcp_table[i].sport) &&
+ (tcphdr->dest == ip_nat_tcp_table[i].dport)) {
+ nat_entry.tcp = &ip_nat_tcp_table[i];
+
+ ip_nat_dbg_dump_tcp_nat_entry("ip_nat_tcp_lookup_outgoing: found existing nat entry: ",
+ nat_entry.tcp);
+ break;
+ }
+ } else {
+ last_free = i;
+ }
+ }
+ if (nat_entry.cmn == NULL) {
+ if (allocate) {
+ if (last_free != -1) {
+ nat_entry.tcp = &ip_nat_tcp_table[last_free];
+ nat_entry.tcp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_TCP_SOURCE_PORT + i));
+ nat_entry.tcp->sport = tcphdr->src;
+ nat_entry.tcp->dport = tcphdr->dest;
+ ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);
+
+ ip_nat_dbg_dump_tcp_nat_entry("ip_nat_tcp_lookup_outgoing: created new nat entry: ",
+ nat_entry.tcp);
+ } else {
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_udp_lookup_outgoing: no more NAT entries available\n"));
+ // rt_kprintf("ip_nat_udp_lookup_outgoing: no more NAT entries available\n");
+ }
+ }
+ }
+ return nat_entry.tcp;
+}
+
+/** Adjusts the checksum of a NAT'ed packet without having to completely recalculate it
+ * @todo: verify this works for little- and big-endian
+ *
+ * @param chksum points to the chksum in the packet
+ * @param optr points to the old data in the packet
+ * @param olen length of old data
+ * @param nptr points to the new data in the packet
+ * @param nlen length of new data
+ */
+static void
+ip_nat_chksum_adjust(u8_t *chksum, const u8_t *optr, s16_t olen, const u8_t *nptr, s16_t nlen)
+{
+ s32_t x, oldval, newval;
+
+ LWIP_ASSERT("NULL != chksum", NULL != chksum);
+ LWIP_ASSERT("NULL != optr", NULL != optr);
+ LWIP_ASSERT("NULL != nptr", NULL != nptr);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_chksum_adjust: chksum=%p, optr=%p, olen=%" U16_F ", nptr=%p, nlen=%" U16_F "\n",
+ chksum, optr, olen, nptr, nlen));
+ x = chksum[0] * 256 + chksum[1];
+ x = ~x & 0xFFFF;
+ while (olen) {
+ oldval = optr[0] * 256 + optr[1];
+ optr += 2;
+ x -= oldval & 0xffff;
+ if (x <= 0) {
+ x--;
+ x &= 0xffff;
+ }
+ olen -= 2;
+ }
+ while (nlen) {
+ newval = nptr[0] * 256 + nptr[1];
+ nptr += 2;
+ x += newval & 0xffff;
+ if (x & 0x10000) {
+ x++;
+ x &= 0xffff;
+ }
+ nlen -= 2;
+ }
+ x = ~x & 0xFFFF;
+ chksum[0] = x / 256;
+ chksum[1] = x & 0xff;
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_chksum_adjust: chksum = 0x%x\n", *((u16_t *) chksum)));
+}
+
+#if defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON)
+/**
+ * This function dumps an IP address
+ *
+ * @param addr IP address
+ */
+static void
+ip_nat_dbg_dump_ip(const ip_addr_t *addr)
+{
+ LWIP_ASSERT("NULL != addr", NULL != addr);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F,
+ ip4_addr1(addr), ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr)));
+}
+
+/**
+ * This function dumps an IP header
+ *
+ * @param msg a message to print
+ * @param iphdr IP header
+ */
+static void
+ip_nat_dbg_dump(const char *msg, const struct ip_hdr *iphdr)
+{
+ LWIP_ASSERT("NULL != msg", NULL != msg);
+ LWIP_ASSERT("NULL != iphdr", NULL != iphdr);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s: IP: (", msg));
+ ip_nat_dbg_dump_ip((ip_addr_t *)&(iphdr->src));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip((ip_addr_t *)&(iphdr->dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F ", chksum=%" U16_F ")\n",
+ ntohs(IPH_ID(iphdr)), ntohs(IPH_CHKSUM(iphdr))));
+}
+
+/**
+ * This function dumps an ICMP echo reply/recho request nat entry.
+ *
+ * @param msg a message to print
+ * @param nat_entry the ICMP NAT entry to print
+ */
+static void
+ip_nat_dbg_dump_icmp_nat_entry(const char *msg, const ip_nat_entries_icmp_t *nat_entry)
+{
+ LWIP_ASSERT("NULL != msg", NULL != msg);
+ LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry);
+ LWIP_ASSERT("NULL != nat_entry->common.cfg", NULL != nat_entry->common.cfg);
+ LWIP_ASSERT("NULL != nat_entry->common.cfg->entry.out_if",
+ NULL != nat_entry->common.cfg->entry.out_if);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s", msg));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ICMP : ("));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.source));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F, ntohs(nat_entry->id)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (", seq=%" U16_F, ntohs(nat_entry->seqno)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (") mapped at ("));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.cfg->entry.out_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F, ntohs(nat_entry->id)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (", seq=%" U16_F, ntohs(nat_entry->seqno)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n"));
+}
+
+/**
+ * This function dumps an TCP nat entry.
+ *
+ * @param msg a message to print
+ * @param nat_entry the TCP NAT entry to print
+ */
+static void
+ip_nat_dbg_dump_tcp_nat_entry(const char *msg, const ip_nat_entries_tcp_t *nat_entry)
+{
+ LWIP_ASSERT("NULL != msg", NULL != msg);
+ LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry);
+ LWIP_ASSERT("NULL != nat_entry->common.cfg", NULL != nat_entry->common.cfg);
+ LWIP_ASSERT("NULL != nat_entry->common.cfg->entry.out_if",
+ NULL != nat_entry->common.cfg->entry.out_if);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s", msg));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("TCP : ("));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.source));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->sport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (") mapped at ("));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.cfg->entry.out_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->nport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n"));
+}
+
+/**
+ * This function dumps a UDP NAT entry.
+ *
+ * @param msg a message to print
+ * @param nat_entry the UDP NAT entry to print
+ */
+static void
+ip_nat_dbg_dump_udp_nat_entry(const char *msg, const ip_nat_entries_udp_t *nat_entry)
+{
+ LWIP_ASSERT("NULL != msg", NULL != msg);
+ LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry);
+ LWIP_ASSERT("NULL != nat_entry->common.cfg", NULL != nat_entry->common.cfg);
+ LWIP_ASSERT("NULL != nat_entry->common.cfg->entry.out_if",
+ NULL != nat_entry->common.cfg->entry.out_if);
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s", msg));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("UDP : ("));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.source));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->sport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (") mapped at ("));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.cfg->entry.out_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->nport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(nat_entry->common.dest));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport)));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n"));
+}
+
+/** Prints some info when creating a new NAT entry */
+static void
+ip_nat_dbg_dump_init(ip_nat_conf_t *ip_nat_cfg_new)
+{
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_init: added new NAT interface\n"));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_init: "));
+ ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.source_net));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/"));
+ ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.source_netmask));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@"));
+ ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.in_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.dest_net));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/"));
+ ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.dest_netmask));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@"));
+ ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.out_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("\n"));
+}
+
+/** Prints some info when removing a NAT entry */
+static void
+ip_nat_dbg_dump_remove(ip_nat_conf_t *cur)
+{
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_remove: removing existing NAT interface\n"));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_remove: "));
+ ip_nat_dbg_dump_ip(&(cur->entry.source_net));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/"));
+ ip_nat_dbg_dump_ip(&(cur->entry.source_netmask));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@"));
+ ip_nat_dbg_dump_ip(&(cur->entry.in_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> "));
+ ip_nat_dbg_dump_ip(&(cur->entry.dest_net));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/"));
+ ip_nat_dbg_dump_ip(&(cur->entry.dest_netmask));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@"));
+ ip_nat_dbg_dump_ip(&(cur->entry.out_if->ip_addr));
+ LWIP_DEBUGF(LWIP_NAT_DEBUG, ("\n"));
+}
+#endif /* defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) */
+
+#endif /* IP_NAT */
diff --git a/components/net/lwip_nat/ipv4_nat.h b/components/net/lwip_nat/ipv4_nat.h
new file mode 100644
index 0000000000..e369c781da
--- /dev/null
+++ b/components/net/lwip_nat/ipv4_nat.h
@@ -0,0 +1,103 @@
+/**
+ * NAT - NAT implementation for lwIP supporting TCP/UDP and ICMP.
+ * Copyright (c) 2009 Christian Walter, ?Embedded Solutions, Vienna 2009.
+ *
+ * Copyright (c) 2010 lwIP project ;-)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ */
+
+/*
+ * File : ipv4_nat.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2015, RT-Thread Development Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2015-01-26 Hichard porting to RT-Thread
+ * 2015-01-27 Bernard code cleanup for lwIP in RT-Thread
+ */
+
+#ifndef __LWIP_NAT_H__
+#define __LWIP_NAT_H__
+
+#include <rtthread.h>
+
+#ifdef LWIP_USING_NAT
+
+#include "lwip/err.h"
+#include "lwip/ip_addr.h"
+#include "lwip/opt.h"
+
+/** Timer interval at which to call ip_nat_tmr() */
+#define LWIP_NAT_TMR_INTERVAL_SEC (30*1000)
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct netif;
+struct pbuf;
+
+typedef struct ip_nat_entry
+{
+ ip_addr_t source_net;
+ ip_addr_t source_netmask;
+ ip_addr_t dest_net;
+ ip_addr_t dest_netmask;
+ struct netif *out_if;
+ struct netif *in_if;
+} ip_nat_entry_t;
+
+void ip_nat_init(void);
+void ip_nat_tmr(void);
+u8_t ip_nat_input(struct pbuf *p);
+u8_t ip_nat_out(struct pbuf *p);
+
+err_t ip_nat_add(const ip_nat_entry_t *new_entry);
+void ip_nat_remove(const ip_nat_entry_t *remove_entry);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* IP_NAT */
+
+#endif /* __LWIP_NAT_H__ */