00001 #ifndef SYSCORESHELL_H 00002 #define SYSCORESHELL_H 00003 /**************************************************** 00004 * 00005 * SysCoreShell 00006 * 00007 * implements a credit protokoll for data transmission 00008 * based upon udp transmission for use on SysCore 00009 * costum Xilinx Virtex4FX board made at 00010 * KIP University Heidelberg 00011 * 00012 * 00013 * 05/08/2008 00014 * version 1.9.0.1 00015 * Norbert Abel 00016 * abel@kip.uni-heidelberg.de 00017 * Stefan Mueller-Klieser 00018 * stefanmk@kip.uni-heidelberg.de 00019 * 00020 * implements 00021 * - ethernet -> arp 00022 * used for local address resolution 00023 * - ethernet -> ip -> udp 00024 * used for data and control transfer 00025 * 00026 * since Version 2.0.0.7 (by S.Linev) 00027 * - add read access to commands lists 00028 * - add reset-FIFO commands in default startDaq sequence (as in Optic) 00029 * 00030 * since Version 2.0.0.5 (by S.Linev) 00031 * - add commands lists emulation 00032 * 00033 * since Version 2.0.0.4 (by S.Linev) 00034 * - add software ROC ID register 00035 * 00036 * since Version 2.0.0.3 (by N.Abel) 00037 * - change addresses 00038 * 00039 * since Version 1.9.0.2 (by S.Linev) 00040 * - Keep support of older message format 00041 * 00042 * since Version 1.9.0.1 (by S.Linev) 00043 * - Convert message format to little endian 00044 * 00045 * since Version 1.7.2.2 (by S.Linev) 00046 * - Add control channel lock if very-long NOper should be executed 00047 * 00048 * since Version 1.7.2.1 (by S.Linev) 00049 * - Add system messages into data stream per PutReg command 00050 * 00051 * since Version 1.7.2.0 (by S.Linev) 00052 * - Reduce number of configurations parameters only to Ethr/Udp 00053 * - Remove any nXYTER specific code 00054 * - Remove any kind of initialization 00055 * - Reduce console commands to absolute minimum 00056 * 00057 * since Version 1.7.1.0 (by S.Linev) 00058 * - Add NOper command to perform several put/get at once 00059 * - Allow two nodes to be permanently "connected" - DAQ and Controller, 00060 * many other observers can run in parallel 00061 * - extend statistic block to show daq status 00062 * 00063 * since Version 1.7.0.6 (by S.Linev) 00064 * - If operation not allowed, return err code 8 (not 7, mixed up with I2C) 00065 * - When uploading firmware, return 0 as normal completion code 00066 * 00067 * since Version 1.7.0.5 (by S.Linev) 00068 * - Fix error with high/low water marker - their were by mistake reset with start daq 00069 * - Add sys message 5 when high water mark is achieved - to see it later in data stream 00070 * 00071 * since Version 1.7.0.4 (by N.Abel) 00072 * - All state transitions logic from PowerPc code was moved into KNUT 00073 * - All correspondent defines are removed from PowerPC side 00074 * 00075 * Changelog: 00076 * since Version 1.6.7.4 (by S.Linev) 00077 * - statistic block can be automatically send when 00078 * poke(ROC_CONSOLE_OUTPUT, 2) was done. This enables debug 00079 * output over UDP port to master controller. Now with debug output 00080 * statistic will be delivered to master terminal 00081 * - statistic block now contains how many time (in relative unit) mainLoop 00082 * spends in data taking, ethernet packets dispatching and data sending 00083 * - maximal optimisation of readout loop - only doing readout (send blocked) 00084 * one achieves 36.5 MB/s by reading OCM registers and 00085 * 12.5 MB/s by reading BURST registers 00086 * 00087 * since Version 1.6.7.3 (by S.Linev) 00088 * - flush timer - either flush data from partially filled buffer or 00089 * resend last buffer to PC 00090 * - small bug-fix in mainLoop - when there was no place in net fifo, 00091 * mainLoop was terminated and reentered again (results in send 00092 * datarate reduction). Now up to 12.3 MB/s outgoing rate is measured 00093 * - statistic block with several datarates, measured together 00094 * 00095 * since Version 1.6.7.2 (by S.Linev) 00096 * - solved (hopefully) problem with half/full diplex, 00097 * function Temac_Reset() seems to be correctly resets TEMAC driver 00098 * - optionally (via config file entry TEMAC_PHYREG0) one can enable 00099 * TEMAC register initialisation, used in previos tapdev_init() version 00100 * - cleanup peek/poke code, poke command can now transoprt 00101 * portion of raw data (for instance, part of bit file or file name) 00102 * - save_config and load_config can store files with different names, 00103 * files should already exists on the SD card 00104 * - upload and overwrite any file on SD-card; 00105 * used for software update, one also can overwrite config files 00106 * - fully configurable port numbers for ROC and host PC 00107 * (to exclude in future potential firewall problems) 00108 * 00109 * since Version 1.6.7.1 (by S.Linev) 00110 * - complete redesign of mainLoop 00111 * - data sending do not block data taking and vise versa 00112 * - as fast as possible goes back to data tacking 00113 * - more than 100MB can be used for storage of messages before they send to PC 00114 * - redesign of protocol - absolute window instead of relative credit counter 00115 * - optimised write to Temac FIFO - operation always 4 bytes alligned 00116 * - separate consoleMainLoop for console output, move most of cmd_xxxx methods to sc_console.c file 00117 * - safe and fast method to upload bitfile (extended peek/poke logic) 00118 * - sc_printf can display data on console, UART or on PC terminal 00119 * 00120 * since Version 1.6.5.0 00121 * - redo of ethernet phy startup code, there was no proper phy init code 00122 * in the xilinx device driver for the intel lxt971a, it is done via MII 00123 * commands 00124 * 00125 * since Version 1.6.0.0 00126 * - Hexadecimal readout of MAC address from SD-Card 00127 * - add define ROC_CONSOLE_OUTPUT to be able to mute all rs232 output 00128 * - you can now PING the ROC 00129 * - Arp cache is done in a different way. ROC uses the Info found in the 00130 * ROC_SET_TARGET_IP packet, which will be send during addBoard() 00131 * 00132 * since Version 1.0.0.0 00133 * - rewrote some of the retransmit code. 00134 * - credits are set to max when DAQ start 00135 * 00136 *****************************************************/ 00137 00138 #define SYSCORE_VERSION 0x02000007 00139 00140 //debuglevel 0 silences the output to nearly zero, 3 makes it loud 00141 #define DEBUGLEVEL 0 00142 00143 #include "defines.h" 00144 00145 #include <ctype.h> //compiliert nicht mit eldk!!! 00146 #include <string.h> 00147 #include <stdarg.h> 00148 #include <stdlib.h> 00149 00150 #include "xbasic_types.h" 00151 #include "xio.h" 00152 #include "xexception_l.h" 00153 #include "xutil.h" 00154 #include "xtime_l.h" 00155 #include "xcache_l.h" 00156 #include "xparameters.h" 00157 #include "xuartlite_l.h" 00158 #include <xuartlite.h> 00159 #include "ddr_header.h" 00160 00161 //console 00162 //#include "tty.h" 00163 00164 //network 00165 #include "tapdev.h" 00166 #include "ether.h" 00167 #include "ip.h" 00168 #include "arp.h" 00169 #include "udp.h" 00170 #include "crc32.h" 00171 00172 //utils 00173 #include "sd_reader.h" 00174 #include "flash_access.h" 00175 00176 00177 /************************************* 00178 * Which address ranges are cacheable? 00179 ************************************/ 00180 00181 /********************* 00182 * N-XITER Control and 00183 * OCM Data Prefetcher 00184 ********************/ 00185 00186 Xuint32 GetReg(int nodekind, Xuint32 addr, Xuint32 *retVal, Xuint8* rawdata, Xuint32* rawdatasize); 00187 Xuint32 PutReg(int nodekind, Xuint32 addr, Xuint32 val, Xuint8* rawdata); 00188 00189 /*************************************** 00190 * translate commands to debug console 00191 ***************************************/ 00192 00193 extern struct sc_config gC; 00194 00195 #define NODE_FORBIDDEN 0 00196 #define NODE_MASTER 1 00197 #define NODE_CONTROL 2 00198 #define NODE_OBSERVER 3 00199 #define NODE_SKIP 4 00200 00201 /***************************************************** 00202 * SysCore Configuration Structure 00203 *****************************************************/ 00204 struct sc_config 00205 { 00206 Xuint8 verbose; // mask 1 - console, 2 - network, 4 - UART 7 - all together 00207 Xuint8 etherAddrSc[ETHER_ADDR_LEN]; 00208 Xuint8 ipAddrSc[IP_ADDR_LEN]; 00209 Xuint16 ctrlPort; 00210 Xuint16 dataPort; 00211 00212 int flushTimeout; // flush timeout for data packet 00213 int burstLoopCnt; // number of burst readouts in one loop 00214 int ocmLoopCnt; // number of com readouts in one loop 00215 00216 int prefetchActive; // burst mode 00217 int global_consolemode; // UART console enable or disable 00218 }; 00219 00220 extern char defConfigFileName[]; 00221 00222 /***************************************************** 00223 * Receive Buffer 00224 * needed for decoding ethernet packets 00225 ****************************************************/ 00226 Xuint8 global_file_buffer[ROC_ETH_FBUF_SIZE];//4MB buffer for uploaded bitfile 00227 00228 /***************************************************** 00229 * SysCore Data Structure 00230 *****************************************************/ 00231 00232 /***************************************************** 00233 * SysCore Protocol Message Packet Structure 00234 *****************************************************/ 00235 00236 00237 00238 struct SysCore_Message_Packet 00239 { 00240 Xuint8 tag; 00241 Xuint8 pad[3]; 00242 Xuint32 password; 00243 Xuint32 id; 00244 Xuint32 address; 00245 Xuint32 value; 00246 }; 00247 00248 00249 #define SCP_HEADER_OFFSET UDP_PAYLOAD_OFFSET 00250 #define SCP_PAYLOAD_OFFSET (SCP_HEADER_OFFSET + sizeof(struct SysCore_Message_Packet)) 00251 #define SCP_MESSAGE_ETHER_FRAME_SIZE (SCP_PAYLOAD_OFFSET + 80) 00252 #define MAX_SCP_PAYLOAD MAX_UDP_PAYLOAD - sizeof(struct SysCore_Message_Packet) 00253 00254 00255 /***************************************************** 00256 * public function declaration 00257 *****************************************************/ 00258 00259 /**************************************** 00260 * int ethernetPacketDispatcher() 00261 * 00262 * dispatches only one packet in FIFO 00263 * autoresponse to arp request in 00264 * 00265 * returns 1 if packet was dispatched 00266 ***************************************/ 00267 int ethernetPacketDispatcher(); 00268 00269 /*************************************** 00270 * Helper 00271 ***************************************/ 00272 void timer_set(XTime *timer, XTime timeoutMS); 00273 Xuint8 timer_expired(XTime *timer); 00274 void swap_byteorder(Xuint8* target, Xuint16 bytes); 00275 00276 /*---------------------------------------------------*/ 00277 /* The purpose of this routine is to output data the */ 00278 /* same as the standard printf function without the */ 00279 /* overhead most run-time libraries involve. Usually */ 00280 /* the printf brings in many kilobytes of code and */ 00281 /* that is unacceptable in most embedded systems. */ 00282 /*---------------------------------------------------*/ 00283 00284 void sc_printf(const char* fmt, ...); 00285 00286 00287 // _____________________ NEW DEFINITIONS _____________________ 00288 00289 struct SysCoreProfile 00290 { 00291 XTime tm1; 00292 XTime tm2; 00293 Xuint32 cnt; 00294 Xuint32 sum; 00295 }; 00296 00297 #define StartProfile(name) \ 00298 static struct SysCoreProfile name = { 0, 0, 0, 0 }; \ 00299 XTime_GetTime(&(name.tm1)); 00300 00301 #define StopProfile(name, limit, label) \ 00302 XTime_GetTime(&(name.tm2)); \ 00303 name.sum += (name.tm2 - name.tm1); \ 00304 if (++name.cnt >= limit) { \ 00305 int irate = (name.sum / name.cnt) * 1000; \ 00306 int drate = irate % XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ; \ 00307 irate = irate / XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ; \ 00308 drate = (drate * 1000) / XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ; \ 00309 xil_printf(label" tm = %d us\r\n", irate*1000 + drate); \ 00310 name.sum = 0; \ 00311 name.cnt = 0; \ 00312 } 00313 00314 struct SysCore_Data_Packet 00315 { 00316 Xuint32 pktid; 00317 Xuint32 lastreqid; 00318 Xuint32 nummsg; 00319 }; 00320 00321 struct SysCore_Data_Request 00322 { 00323 Xuint32 password; 00324 Xuint32 reqpktid; 00325 Xuint32 frontpktid; 00326 Xuint32 tailpktid; 00327 Xuint32 numresend; 00328 }; 00329 00330 struct sc_statistic { 00331 Xuint32 dataRate; // data taking rate in B/s 00332 Xuint32 sendRate; // network send rate in B/s 00333 Xuint32 recvRate; // network recv rate in B/s 00334 Xuint32 nopRate; // double-NOP messages 1/s 00335 Xuint32 frameRate; // unrecognised frames 1/s 00336 Xuint32 takePerf; // relative use of time for data taing (*100000) 00337 Xuint32 dispPerf; // relative use of time for packets dispatching (*100000) 00338 Xuint32 sendPerf; // relative use of time for data sending (*100000) 00339 Xuint32 daqState; // current daq state 00340 }; 00341 00342 00343 #define RESEND_MAX_SIZE 128 00344 00345 // in 5 seconds master recognised as disconnected 00346 #define MASTER_DISCONNECT_TIME 500 00347 00348 // in 2 seconds control lock should be released 00349 #define LOCK_RELEASE_TIME 200 00350 00351 00352 struct sc_data 00353 { 00354 int rocNumber; /* roc number */ 00355 00356 Xuint8 **buf; /* main buffer with all packages inside, only payload without headers */ 00357 Xuint32 numalloc; /* number of allocated items in buffer */ 00358 00359 // Xuint8 udpheader[UDP_PAYLOAD_OFFSET]; 00360 00361 Xuint32 head; /* buffer which is now filled */ 00362 Xuint32 numbuf; /* number of filled buffers*/ 00363 Xuint32 headid; /* id of the buffer in the head */ 00364 00365 Xuint32 high_water; /* Maximum number of buffers to be used in normal situation */ 00366 Xuint32 low_water; /* Number of buffers to enable data taking after is was stopped */ 00367 unsigned char data_taking_on; /* indicate if we can take new buffer */ 00368 00369 Xuint32 send_head; /* buffer which must be send next */ 00370 Xuint32 send_limit; /* limit for sending - can be in front of existing header */ 00371 00372 Xuint32 resend_indx[RESEND_MAX_SIZE]; /* indexes of buffers which should be resended */ 00373 Xuint32 resend_size; /* number of indexes to be resended */ 00374 00375 Xuint32 last_req_pkt_id; /* id of last request packet, should be always send back */ 00376 00377 struct SysCore_Data_Packet* curr_pkt; 00378 Xuint8* curr_target; 00379 00380 Xuint8 recv_buf[MAX_ETHER_FRAME_SIZE]; 00381 Xuint8 send_buf[MAX_ETHER_FRAME_SIZE]; 00382 00383 int msgformat; // 0 - old format, 1 - current format 00384 00385 00386 // block of master (or DAQ) data 00387 00388 int masterConnected; // 1 if master is connected 00389 int masterCounter; // reverse counter for master connection 00390 00391 Xuint16 masterPort; 00392 Xuint16 masterDataPort; 00393 Xuint8 masterIp[IP_ADDR_LEN]; 00394 Xuint8 masterEther[ETHER_ADDR_LEN]; 00395 00396 Xuint32 lastMasterPacketId; 00397 Xuint8 master_retry_buf[MAX_ETHER_FRAME_SIZE]; 00398 Xuint32 master_retry_buf_rawsize; 00399 00400 // block of controller data 00401 00402 int controlConnected; // 1 if controller is connected 00403 int controlCounter; // reverse counter to "forget" controller connection 00404 00405 Xuint16 controlPort; 00406 Xuint8 controlIp[IP_ADDR_LEN]; 00407 Xuint8 controlEther[ETHER_ADDR_LEN]; 00408 00409 Xuint32 lastControlPacketId; 00410 Xuint8 control_retry_buf[MAX_ETHER_FRAME_SIZE]; 00411 Xuint32 control_retry_buf_rawsize; 00412 00413 // block for control locking 00414 00415 int controlLocked; // 1 if control locked by master, 2 - if by controller 00416 int lockCounter; // reverse counter to unlock control 00417 00418 unsigned daqState; 00419 00420 XTime lastFlushTime; 00421 00422 unsigned etherFramesOtherIpOrArp; 00423 00424 Xuint32 xor0buff; 00425 Xuint32 xor1buff; 00426 00427 struct sc_statistic stat; // statistic block 00428 XTime lastStatTime; 00429 00430 char debugOutput[1024]; // last message over sc_printf 00431 00432 Xuint32 CurrentFlashFileBufferAddress; 00433 00434 Xuint32 cmdsList[ROC_CMD_LST_SIZE/4]; // memory for commands lists 00435 00436 Xuint32 cmdListPtr; // pointer on current active command in the list, 00437 }; 00438 00439 extern struct sc_data gD; 00440 extern struct sc_statistic gCnt; // counter to accumulate statistic 00441 00442 00443 void resetBuffers(int full); 00444 void processDataRequest(struct SysCore_Data_Request* req); 00445 void addSystemMessage(Xuint8 id, int flush); 00446 void sendConsoleData(Xuint32 addr, void* data, unsigned payloadSize); 00447 int overwriteSDFile(); 00448 00449 #endif