Other Parts Discussed in Thread: C2000WARE
使用C2000Ware_6_00_00_00\libraries\communications\Ethernet\third_party\lwip\examples\enet_lwip_udp例程,修改原来测试接口。在udp_rx_callback中接收到数据立即发送接受到得数据给发送端;
在主循环中分5ms,11ms,1001ms.1002ms,1003ms,1204ms,1505ms ,主动像外发送数据,运行一段时间后。
程序进入NmiSR,
测试程序只修改了enet_lwip_udp.c,全部代码如下:
//###########################################################################
//
// FILE: enet_lwip.c
//
// TITLE: lwIP based Ethernet Example.
//
// Example to demonstrate UDP socket (for daikin customer)
// buf_rx,buf_tx are the watch variables which can be used or updated in the
// main application based on the requirement.
//
// Test setup
//
// F2838x Control Card connected to a PC/laptop on the Ethernet port.
// PC/laptop runs the SocketTest/鈥橮acket Sender鈥� software, configured for the IP Address and port . \
// Keywords 鈥楽TART鈥� and 鈥楽TOP鈥� are used to send and stop receiving messages respectively
// Received data is stored in 鈥榖uf_rx鈥� array and data to be transmitted is stored in 鈥榖uf_tx鈥� array on CM core of F2838x device
// Examples is Interrupt based with a callback function 鈥榰dp_rx_callback鈥� which handles the received data from the SocketTest/Packet Sender software.
//
//###########################################################################
// $TI Release: $
// $Release Date: $
//
// C2000Ware v6.00.00.00
//
// Copyright (C) 2024 Texas Instruments Incorporated - http://www.ti.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 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.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 COPYRIGHT
// OWNER OR CONTRIBUTORS 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.
// $
//###########################################################################
#include <string.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_emac.h"
#include "driverlib_cm/ethernet.h"
#include "driverlib_cm/gpio.h"
#include "driverlib_cm/interrupt.h"
#include "driverlib_cm/flash.h"
#include "driverlib_cm/sysctl.h"
#include "driverlib_cm/systick.h"
#include "utils/lwiplib.h"
#include "driver/device.h"
#include "driver/ethernet.h"
#include "board_drivers/pinout.h"
#include "lwipopts.h"
//*****************************************************************************
//
//! \addtogroup master_example_list
//! <h1>Ethernet with lwIP (enet_lwip)</h1>
//!
//! This example application demonstrates the operation of the F2838x
//! microcontroller Ethernet controller using the lwIP TCP/IP Stack. Once
//! programmed, the device sits endlessly waiting for ICMP ping requests. It
//! has a static IP address. To ping the device, the sender has to be in the
//! same network. The stack also supports ARP.
//!
//! For additional details on lwIP, refer to the lwIP web page at:
//! savannah.nongnu.org/.../
//
//*****************************************************************************
#define MAKE_IP_ADDRESS(a0,a1,a2,a3) (((a0<<24) & 0xFF000000) | ((a1<<16) & 0x00FF0000) | ((a2<<8) & 0x0000FF00) | (a3 & 0x000000FF) )
#define PAYLOAD 1088
#define RX_ISR_BIT 1
#define TX_ISR_BIT 4
#define TMR_ISR_BIT 8
#define RX_ISR_MASK (1 << RX_ISR_BIT)
#define TX_ISR_MASK (1 << TX_ISR_BIT)
#define TMR_ISR_MASK (1 << TMR_ISR_BIT)
/*
g_uiISRsignal variable signal the ISR.
*/
uint32_t g_uiISRsignal = 0;
const unsigned long IPAddr = 0xC0A8250C; // 0xC0A80004; //192.168.0.4
const unsigned long NetMask = 0xFFFFFF00;
const unsigned long GWAddr = 0x00000000;
Ethernet_Handle emac_handle;
Ethernet_InitConfig *pInitCfg;
extern Ethernet_Device Ethernet_device_struct;
/*
systick Timer acts as lwip Timer,
125000 implies 1ms.
*/
const uint32_t systickPeriodValue = 125000;
volatile uint32_t msTime=0;
volatile bool flag_TX_frame_UDP=true;
bool Connected_udp_28000 = false;
uint16_t cnt_Connected_udp_28000 = 0;
struct udp_pcb *g_upcb;
u8_t buf_rx[PAYLOAD];
u8_t buf_tx[PAYLOAD];
char * buf_tx_start_msg = "Something to show UDP is working \n";
uint32_t buf_tx_start_msg_count = 35;
uint16_t cont_rx_udp = 0;
uint32_t systic_ms = 0;
struct pbuf *pbuf1_tx;
/***********************************************************************************************
* Ethernet_transmitISRCustom
*
* This function is a custom interrupt service routine (ISR) for handling Ethernet
* transmission interrupts. It is called when a packet is succesfully transmitted.
*
************************************************************************************************/
void Ethernet_transmitISRCustom(void);
/************************************************************************************************
* Ethernet_receiveISRCustom
*
* This function is a custom interrupt service routine (ISR) for handling Ethernet
* reception interrupts. It is called when a packet is received.
*
************************************************************************************************/
void Ethernet_receiveISRCustom(void);
//*****************************************************************************
//
// This function is a callback function called by the example to
// get a Packet Buffer. Has to return a Ethernet_Pkt_Desc Structure.
// Rewrite this API for custom use case.
//
//*****************************************************************************
Ethernet_Pkt_Desc* Ethernet_getPacketBufferCustom(void)
{
Ethernet_Pkt_Desc* pktPtr = lwIP_getFreePacket();
ENET_DRIVER_STATS_INC(RXgetPacketBuffer);
return (pktPtr);
}
//*****************************************************************************
//
// This is a hook function and called by the driver when it receives a
// packet. Application is expected to replenish the buffer after consuming it.
// Has to return a ETHERNET_Pkt_Desc Structure.
// Rewrite this API for custom use case.
//
//*****************************************************************************
Ethernet_Pkt_Desc* Ethernet_receivePacketCallbackCustom(
Ethernet_Handle handleApplication,
Ethernet_Pkt_Desc *pPacket)
{
Ethernet_Pkt_Desc* temp_eth_pkt;
ENET_DRIVER_STATS_INC(RXPacketCallback);
temp_eth_pkt=lwIPEthernetIntHandler(pPacket);
return temp_eth_pkt;
}
void Ethernet_releaseTxPacketBufferCustom(
Ethernet_Handle handleApplication,
Ethernet_Pkt_Desc *pPacket)
{
//
// Once the packet is sent, reuse the packet memory to avoid
// memory leaks. Call this interrupt handler function which will take care
// of freeing the memory used by the packet descriptor.
//
lwIPEthernetIntHandler(pPacket);
ENET_DRIVER_STATS_INC(TXreleasePacket);
}
void
Ethernet_init(const unsigned char *mac)
{
Ethernet_InitInterfaceConfig initInterfaceConfig;
uint32_t macLower;
uint32_t macHigher;
uint8_t *temp;
initInterfaceConfig.ssbase = EMAC_SS_BASE;
initInterfaceConfig.enet_base = EMAC_BASE;
initInterfaceConfig.phyMode = ETHERNET_SS_PHY_INTF_SEL_MII;
//
// Assign SoC specific functions for Enabling,Disabling interrupts
// and for enabling the Peripheral at system level
//
initInterfaceConfig.ptrPlatformInterruptDisable =
&Platform_disableInterrupt;
initInterfaceConfig.ptrPlatformInterruptEnable =
&Platform_enableInterrupt;
initInterfaceConfig.ptrPlatformPeripheralEnable =
&Platform_enablePeripheral;
initInterfaceConfig.ptrPlatformPeripheralReset =
&Platform_resetPeripheral;
//
// Assign the peripheral number at the SoC
//
initInterfaceConfig.peripheralNum = SYSCTL_PERIPH_CLK_ENET;
//
// Assign the default SoC specific interrupt numbers of Ethernet interrupts
//
initInterfaceConfig.interruptNum[0] = INT_EMAC;
initInterfaceConfig.interruptNum[1] = INT_EMAC_TX0;
initInterfaceConfig.interruptNum[2] = INT_EMAC_TX1;
initInterfaceConfig.interruptNum[3] = INT_EMAC_RX0;
initInterfaceConfig.interruptNum[4] = INT_EMAC_RX1;
pInitCfg = Ethernet_initInterface(initInterfaceConfig);
Ethernet_getInitConfig(pInitCfg);
pInitCfg->dmaMode.InterruptMode = ETHERNET_DMA_MODE_INTM_MODE2;
//
// Assign the callbacks for Getting packet buffer when needed
// Releasing the TxPacketBuffer on Transmit interrupt callbacks
// Receive packet callback on Receive packet completion interrupt
//
pInitCfg->pfcbRxPacket = &Ethernet_receivePacketCallbackCustom;
pInitCfg->pfcbGetPacket = &Ethernet_getPacketBufferCustom;
pInitCfg->pfcbFreePacket = &Ethernet_releaseTxPacketBufferCustom;
pInitCfg->numChannels = 1U;
//
// The Application handle is not used by this application
// Hence using a dummy value of 1
//
Ethernet_getHandle((Ethernet_Handle)1, pInitCfg , &emac_handle);
//
// Disable transmit buffer unavailable and normal interrupt which
// are enabled by default in Ethernet_getHandle.
//
Ethernet_disableDmaInterrupt(Ethernet_device_struct.baseAddresses.enet_base,
0, (ETHERNET_DMA_CH0_INTERRUPT_ENABLE_TBUE |
ETHERNET_DMA_CH0_INTERRUPT_ENABLE_NIE));
//
// Enable the MTL interrupt to service the receive FIFO overflow
// condition in the Ethernet module.
//
Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOIE);
//
// Disable the MAC Management counter interrupts as they are not used
// in this application.
//
HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_IPC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_TX_INTERRUPT_MASK) = 0xFFFFFFFF;
//
//Do global Interrupt Enable
//
(void)Interrupt_enableInProcessor();
//
//Assign default ISRs
//
Interrupt_registerHandler(INT_EMAC_TX0, Ethernet_transmitISRCustom);
Interrupt_registerHandler(INT_EMAC_RX0, Ethernet_receiveISRCustom);
Interrupt_registerHandler(INT_EMAC, Ethernet_genericISRCustom);
//
// Convert the mac address string into the 32/16 split variables format
// that is required by the driver to program into hardware registers.
// Note: This step is done after the Ethernet_getHandle function because
// a dummy MAC address is programmed in that function.
//
temp = (uint8_t *)&macLower;
temp[0] = mac[0];
temp[1] = mac[1];
temp[2] = mac[2];
temp[3] = mac[3];
temp = (uint8_t *)&macHigher;
temp[0] = mac[4];
temp[1] = mac[5];
//
// Program the unicast mac address.
//
Ethernet_setMACAddr(EMAC_BASE,
0,
macHigher,
macLower,
ETHERNET_CHANNEL_0);
Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
}
void httpLEDToggle(void);
void(*ledtoggleFuncPtr)(void) = &httpLEDToggle;
//*****************************************************************************
//
// The interrupt handler for the SysTick interrupt.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
//
// Call the lwIP timer handler.
//
systic_ms++;
lwIPTimer(1);
}
int16_t udp_send_data(uint8_t *buf, uint16_t len,uint32_t addr ,uint16_t port)
{
err_t err;
ip_addr_t remote_ip;
struct pbuf *buf_send;
if((len == 0) || (len >= 1200))
{
return -1;
}
buf_send = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (buf_send == NULL)
{
return -1;
}
remote_ip.addr = addr;
/* copy data to pbuf */
err = pbuf_take(buf_send, (char*)buf, len);
if(err != ERR_OK)
{
pbuf_free(buf_send);
return -1;
}
/* send udp data */
err = udp_sendto(g_upcb, buf_send, &remote_ip, port);
if(err != ERR_OK)
{
pbuf_free(buf_send);
return -1;
}
pbuf_free(buf_send);
return 0;
}
#define ETH_BUF_MAX_SIZE 1200
#define RX_CACL_CRC_OFFSET 8
static uint32_t recv_err_cnt=0;
static uint32_t recv_ok_cnt=0;
static uint32_t recv_cnt=0;
static uint8_t rx_pack_buff[ETH_BUF_MAX_SIZE];
static uint8_t tx_pack_buff[ETH_BUF_MAX_SIZE];
static uint8_t tx1_pack_buff[ETH_BUF_MAX_SIZE];
int32_t udp_get_data( struct pbuf *p,uint8_t *data){
struct pbuf *q;
int32_t cut_Len = 0;
if(p != NULL){
for(q=p;q!=NULL;q=q->next)
{
if(q->len > (ETH_BUF_MAX_SIZE-cut_Len))
{
memcpy(data+cut_Len,q->payload,(ETH_BUF_MAX_SIZE-cut_Len));
cut_Len = ETH_BUF_MAX_SIZE;
}
else
{
memcpy(data+cut_Len,q->payload,q->len);
cut_Len += q->len;
}
if(cut_Len >= ETH_BUF_MAX_SIZE)
{
cut_Len = ETH_BUF_MAX_SIZE;
break;
}
}
}
return cut_Len;
}
void udp_rx_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p,
const ip_addr_t *addr, u16_t port)
{
int32_t rx_data_len = 0;
rx_data_len=udp_get_data(p,rx_pack_buff);
pbuf_free(p);
recv_cnt++;
#if 0
int32_t i;
for(i=0;i<1024;i++){
if(rx_pack_buff[i]!=(uint8_t)i){
recv_err_cnt++;
return;
}
}
#endif
memcpy(tx1_pack_buff,rx_pack_buff,rx_data_len);
udp_send_data(tx1_pack_buff,rx_data_len,addr->addr,port);
recv_ok_cnt++;
}
/* UDP initialization ......................................................*/
void my_udp_init(void)
{
g_upcb = udp_new();
udp_bind(g_upcb, IP_ADDR_ANY, 28000);
udp_recv(g_upcb, &udp_rx_callback, (void*) 0);
}
/*
Timer0 ISR to signal at a specific delay
*/
void timerInterruptHandler()
{
g_uiISRsignal |= TMR_ISR_MASK;
}
//*****************************************************************************
//
// This example demonstrates the use of the Ethernet Controller.
//
//*****************************************************************************
void send_active(void);
int
main(void)
{
unsigned long ulUser0, ulUser1;
unsigned char pucMACArray[8];
int i=0;
// ////////////////////////////////////////
// Initializing the CM. Loading the required functions to SRAM.
//
CM_init();
SYSTICK_setPeriod(systickPeriodValue);
SYSTICK_enableCounter();
SYSTICK_registerInterruptHandler(SysTickIntHandler);
SYSTICK_enableInterrupt();
//
// Enable processor interrupts.
//
Interrupt_enableInProcessor();
// Set user/company specific MAC octets
// (for this code we are using A8-63-F2-00-00-80)
// 0x00 MACOCT3 MACOCT2 MACOCT1
ulUser0 = 0x00F263A8;
// 0x00 MACOCT6 MACOCT5 MACOCT4
ulUser1 = 0x00800000;
//
// Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
// address needed to program the hardware registers, then program the MAC
// address into the Ethernet Controller registers.
//
pucMACArray[0] = ((ulUser0 >> 0) & 0xff);
pucMACArray[1] = ((ulUser0 >> 8) & 0xff);
pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
pucMACArray[3] = ((ulUser1 >> 0) & 0xff);
pucMACArray[4] = ((ulUser1 >> 8) & 0xff);
pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
//
// Initialze the lwIP library, using DHCP.
//
lwIPInit(0, pucMACArray, IPAddr, NetMask, GWAddr, IPADDR_USE_STATIC);
//
// Initialize ethernet module.
//
Ethernet_init(pucMACArray);
//
// Initialize the netif and start lwIP
//
lwIPStart(0);
//
//Initialize the timer module
//
//initTimer0(timerInterruptHandler);
// configCPUTimer0(10000); //1sec delay
// startTimer0();
// Initialize the UDP server
//
my_udp_init();
//
// Loop forever. All the work is done in interrupt handlers.
//
uint32_t cnt_FFT = 0;
Interrupt_setPriority(INT_EMAC_TX0, 2);
Interrupt_setPriority(INT_EMAC_RX0, 1);
Interrupt_enable(INT_EMAC_TX0);
Interrupt_enable(INT_EMAC_RX0);
Interrupt_enable(INT_EMAC);
// Interrupt_enable(INT_TIMER0);
volatile int cnt_total_loop=0;
volatile int cnt_total_mqtt_pub=0;
while (1)
{
#if 0
uint32_t uiISRsignal = g_uiISRsignal;
if((uiISRsignal & RX_ISR_MASK) != 0)
{
ETHERNET_DISABLE_INTERRUPTS();
g_uiISRsignal &= (~RX_ISR_MASK);
ETHERNET_ENABLE_INTERRUPTS();
}
if((uiISRsignal & TX_ISR_MASK) != 0)
{
ETHERNET_DISABLE_INTERRUPTS();
g_uiISRsignal &= (~TX_ISR_MASK);
ETHERNET_ENABLE_INTERRUPTS();
}
if((uiISRsignal & TMR_ISR_MASK) != 0)
{
cnt_total_loop++;
if (Connected_udp_28000)
{
//UDP TX block
if (flag_TX_frame_UDP)
{
cnt_FFT++;
//flag_TX_frame_UDP = false;
/////////////////////////////////////////////
for (i = 0; i < PAYLOAD; i++)
{
if(i < buf_tx_start_msg_count)
{
buf_tx[i] = (uint8_t)buf_tx_start_msg[i];
}
else
{
buf_tx[i] = (uint8_t) (cnt_FFT);
}
}
////////////////////////////////////////////
pbuf1_tx = pbuf_alloc(PBUF_TRANSPORT, PAYLOAD, PBUF_RAM);
if (pbuf1_tx!= NULL)
{
pbuf1_tx->payload = (void*) buf_tx;
pbuf1_tx->tot_len = PAYLOAD; // long_UDP_complete+4;
pbuf1_tx->len = PAYLOAD; // long_UDP_complete+4;
udp_send(g_upcb, pbuf1_tx);
}
cnt_Connected_udp_28000++;
if (pbuf1_tx!= NULL)
pbuf_free(pbuf1_tx);
}
}
#endif
sys_check_timeouts();
send_active();
ETHERNET_DISABLE_INTERRUPTS();
g_uiISRsignal &= (~TMR_ISR_MASK);
ETHERNET_ENABLE_INTERRUPTS();
// }
}
}
void Ethernet_transmitISRCustom(void)
{
ENET_DRIVER_STATS_INC(TXinterrupt);
Ethernet_clearDMAChannelInterrupt(
Ethernet_device_struct.baseAddresses.enet_base,
ETHERNET_DMA_CHANNEL_NUM_0,
ETHERNET_DMA_CH0_STATUS_TI);
Ethernet_removePacketsFromTxQueueCustom(
(Ethernet_DescCh*)&Ethernet_device_struct.dmaObj.txDma[ETHERNET_DMA_CHANNEL_NUM_0], ETHERNET_COMPLETION_NORMAL);
g_uiISRsignal |= TX_ISR_MASK;
}
void Ethernet_receiveISRCustom(void)
{
ENET_DRIVER_STATS_INC(RXinterrupt);
Ethernet_clearDMAChannelInterrupt(
Ethernet_device_struct.baseAddresses.enet_base,
ETHERNET_DMA_CHANNEL_NUM_0,
ETHERNET_DMA_CH0_STATUS_RI);
Ethernet_removePacketsFromRxQueueCustom(
(Ethernet_DescCh*)&Ethernet_device_struct.dmaObj.rxDma[ETHERNET_DMA_CHANNEL_NUM_0], ETHERNET_COMPLETION_NORMAL);
g_uiISRsignal |= RX_ISR_MASK;
}
//*****************************************************************************
//
// Called by lwIP Library. Toggles the led when a command is received by the
// HTTP webserver.
//
//*****************************************************************************
void httpLEDToggle(void)
{
//
// Toggle the LED D1 on the control card.
//
GPIO_togglePin(DEVICE_GPIO_PIN_LED1);
}
//*****************************************************************************
//
// Called by lwIP Library. Could be used for periodic custom tasks.
//
//*****************************************************************************
uint32_t cnt_ms_lwip_Htimer=0;
uint32_t cnt_ms_TX_Htimer=0;
void lwIPHostTimerHandler(void)
{
// msTime++;
cnt_ms_lwip_Htimer++;
}
void send_active(void){
if(systic_ms%5==0){
udp_send_data(tx_pack_buff,500,0x7925A8C0,9260);
}
if(systic_ms%11==0){
udp_send_data(tx_pack_buff,500,0x7925A8C0,9260);
}
if(systic_ms%1001==0){
udp_send_data(tx_pack_buff,300,0x7925A8C0,9260);
}
if(systic_ms%1002==0){
udp_send_data(tx_pack_buff,1000,0x7925A8C0,9260);
}
if(systic_ms%1003==0){
udp_send_data(tx_pack_buff,1000,0x7925A8C0,9260);
}
if(systic_ms%1204==0){
udp_send_data(tx_pack_buff,1100,0x7925A8C0,9260);
}
if(systic_ms%1505==0){
udp_send_data(tx_pack_buff,100,0x7925A8C0,9260);
}
}