From f85e3a62b32f25c76e6c6f214938b6b7f8191d66 Mon Sep 17 00:00:00 2001 From: Harini Katakam Date: Tue, 21 Jul 2015 15:56:37 +0530 Subject: [PATCH] lwip_echo_server: Add support for Zynq Ultrascale MPSoC Add a separate platform file for Zynq Ultrascale MPSoC using the respective timer and driver functions. The platform selection is based on the processor recognized in the tcl file. Signed-off-by: Harini Katakam Reviewed-by: Anirudha Sarangi --- lib/sw_apps/lwip_echo_server/src/main.c | 2 + .../lwip_echo_server/src/platform_zynq.c | 8 +- .../lwip_echo_server/src/platform_zynqmp.c | 191 ++++++++++++++++++ 3 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 lib/sw_apps/lwip_echo_server/src/platform_zynqmp.c diff --git a/lib/sw_apps/lwip_echo_server/src/main.c b/lib/sw_apps/lwip_echo_server/src/main.c index 4945b0d0..f1ce06f0 100644 --- a/lib/sw_apps/lwip_echo_server/src/main.c +++ b/lib/sw_apps/lwip_echo_server/src/main.c @@ -52,6 +52,8 @@ void print_app_header(); int start_application(); int transfer_data(); +void tcp_fasttmr(void); +void tcp_slowtmr(void); /* missing declaration in lwIP */ void lwip_init(); diff --git a/lib/sw_apps/lwip_echo_server/src/platform_zynq.c b/lib/sw_apps/lwip_echo_server/src/platform_zynq.c index 82eda69b..6ec05985 100644 --- a/lib/sw_apps/lwip_echo_server/src/platform_zynq.c +++ b/lib/sw_apps/lwip_echo_server/src/platform_zynq.c @@ -55,16 +55,17 @@ #include "xparameters_ps.h" /* defines XPAR values */ #include "xil_cache.h" #include "xscugic.h" -#include "xscutimer.h" #include "lwip/tcp.h" #include "xil_printf.h" #include "platform_config.h" #include "netif/xadapter.h" +#ifdef PLATFORM_ZYNQ +#include "xscutimer.h" #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #define TIMER_DEVICE_ID XPAR_SCUTIMER_DEVICE_ID -#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR -#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR +#define INTC_BASE_ADDR XPAR_SCUGIC_0_CPU_BASEADDR +#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_0_DIST_BASEADDR #define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR #define RESET_RX_CNTR_LIMIT 400 @@ -225,4 +226,5 @@ void cleanup_platform() return; } #endif +#endif diff --git a/lib/sw_apps/lwip_echo_server/src/platform_zynqmp.c b/lib/sw_apps/lwip_echo_server/src/platform_zynqmp.c new file mode 100644 index 00000000..9966bc18 --- /dev/null +++ b/lib/sw_apps/lwip_echo_server/src/platform_zynqmp.c @@ -0,0 +1,191 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/* +* platform_zynqmp.c +* +* ZynqMP platform specific functions. +* +* +* + */ + +#ifdef __arm__ + +#include "xparameters.h" +#include "xparameters_ps.h" /* defines XPAR values */ +#include "xil_cache.h" +#include "xscugic.h" +#include "lwip/tcp.h" +#include "xil_printf.h" +#include "platform_config.h" +#include "netif/xadapter.h" +#ifdef PLATFORM_ZYNQMP +#include "xttcps.h" + +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define TIMER_DEVICE_ID XPAR_XTTCPS_0_DEVICE_ID +#define TIMER_IRPT_INTR XPAR_XTTCPS_0_INTR +#define INTC_BASE_ADDR XPAR_SCUGIC_0_CPU_BASEADDR +#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_0_DIST_BASEADDR + +#define PLATFORM_TIMER_INTR_RATE_HZ (4) + +static XTtcPs TimerInstance; +static u16 Interval; +static u8 Prescaler; + +volatile int TcpFastTmrFlag = 0; +volatile int TcpSlowTmrFlag = 0; + +#if LWIP_DHCP==1 +volatile int dhcp_timoutcntr = 24; +void dhcp_fine_tmr(); +void dhcp_coarse_tmr(); +#endif + +void platform_clear_interrupt( XTtcPs * TimerInstance ); + +void +timer_callback(XTtcPs * TimerInstance) +{ + /* we need to call tcp_fasttmr & tcp_slowtmr at intervals specified + * by lwIP. It is not important that the timing is absoluetly accurate. + */ + static int odd = 1; +#if LWIP_DHCP==1 + static int dhcp_timer = 0; +#endif + TcpFastTmrFlag = 1; + odd = !odd; + if (odd) { +#if LWIP_DHCP==1 + dhcp_timer++; + dhcp_timoutcntr--; +#endif + TcpSlowTmrFlag = 1; +#if LWIP_DHCP==1 + dhcp_fine_tmr(); + if (dhcp_timer >= 120) { + dhcp_coarse_tmr(); + dhcp_timer = 0; + } +#endif + } + platform_clear_interrupt(TimerInstance); +} + +void platform_setup_timer(void) +{ + int Status; + XTtcPs * Timer = &TimerInstance; + XTtcPs_Config *Config; + + + Config = XTtcPs_LookupConfig(TIMER_DEVICE_ID); + + Status = XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + xil_printf("In %s: Timer Cfg initialization failed...\r\n", + __func__); + return; + } + XTtcPs_SetOptions(Timer, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE); + XTtcPs_CalcIntervalFromFreq(Timer, PLATFORM_TIMER_INTR_RATE_HZ, &Interval, &Prescaler); + XTtcPs_SetInterval(Timer, Interval); + XTtcPs_SetPrescaler(Timer, Prescaler); +} + +void platform_clear_interrupt( XTtcPs * TimerInstance ) +{ + u32 StatusEvent; + + StatusEvent = XTtcPs_GetInterruptStatus(TimerInstance); + XTtcPs_ClearInterruptStatus(TimerInstance, StatusEvent); +} + +void platform_setup_interrupts(void) +{ + Xil_ExceptionInit(); + + XScuGic_DeviceInitialize(INTC_DEVICE_ID); + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, + (void *)INTC_DEVICE_ID); + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + XScuGic_RegisterHandler(INTC_BASE_ADDR, TIMER_IRPT_INTR, + (Xil_ExceptionHandler)timer_callback, + (void *)&TimerInstance); + /* + * Enable the interrupt for scu timer. + */ + XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, TIMER_IRPT_INTR); + + return; +} + +void platform_enable_interrupts() +{ + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); + XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, TIMER_IRPT_INTR); + XTtcPs_EnableInterrupts(&TimerInstance, XTTCPS_IXR_INTERVAL_MASK); + XTtcPs_Start(&TimerInstance); + return; +} + +void init_platform() +{ + platform_setup_timer(); + platform_setup_interrupts(); + + return; +} + +void cleanup_platform() +{ + Xil_ICacheDisable(); + Xil_DCacheDisable(); + return; +} +#endif +#endif