source: ResearchApps/PHY/WARPLAB/WARPLab7/C_Code_Reference/wl_common.c

Last change on this file was 4758, checked in by welsh, 9 years ago

Updated to WL 7.6.1; Fixed issue with send_early_response; default error printing level

File size: 37.6 KB
RevLine 
[4184]1/** @file wl_common.c
2 *  @brief WARPLab Framework (Common)
3 *
4 *  This contains the code for WARPLab Framework.
5 *
[4668]6 *  @copyright Copyright 2013-2015, Mango Communications. All rights reserved.
[4184]7 *          Distributed under the WARP license  (http://warpproject.org/license)
8 *
9 *  @author Chris Hunter (chunter [at] mangocomm.com)
10 *  @author Patrick Murphy (murphpo [at] mangocomm.com)
11 *  @author Erik Welsh (welsh [at] mangocomm.com)
12 */
[1915]13
[4453]14
15/**********************************************************************************************************************/
16/**
[4668]17 * @brief Common Functions
[4453]18 *
19 **********************************************************************************************************************/
20
21
[4184]22/***************************** Include Files *********************************/
[1915]23
[4184]24// Xilinx / Standard library includes
[1915]25#include <xparameters.h>
[4184]26#include <xil_io.h>
27#include <xio.h>
28
[4453]29//#include "stdlib.h"
30//#include "ctype.h"
[4184]31#include "string.h"
[4453]32//#include "stdarg.h"
[2013]33#include "stdio.h"
[1915]34
[4184]35// Xilinx Peripheral includes
[4453]36#include <xtmrctr.h>
[4184]37#include <xgpio.h>
[1915]38
[4184]39// WARPLab includes
40#include "wl_common.h"
[4316]41#include "wl_node.h"
[4196]42#include "wl_baseband.h"
[2013]43
[4184]44
45/*************************** Constant Definitions ****************************/
46
[4668]47#define TMRCTR_DEVICE_ID                                   XPAR_TMRCTR_0_DEVICE_ID
48#define TIMER_FREQ                                         XPAR_TMRCTR_0_CLOCK_FREQ_HZ
49#define TIMER_COUNTER_0                                    0
[4196]50
51
[1915]52
[4184]53/*********************** Global Variable Definitions *************************/
54
55/*************************** Variable Definitions ****************************/
56
[4196]57// Peripheral Instances
58static XTmrCtr                    TimerCounter;                 ///< Instance of the Tmrctr device
59static XGpio                      GPIO_debugpin;                ///< Instance of the GPIO device
[4184]60
61
[4292]62#if _DEBUG_STORAGE_
63u32                debug_storage[_DEBUG_STORAGE_SIZE_];
64u32                storage_index = 0;
65#endif
[4284]66
[4292]67
[4453]68
[4184]69/*************************** Functions Prototypes ****************************/
70
[4196]71/******************************** Functions **********************************/
[4184]72
[4453]73/*****************************************************************************
74 *
75 * Debug Printing Functions
76 *
77 *****************************************************************************/
[4758]78u8       wl_print_level           = DEFAULT_DEBUG_PRINT_LEVEL;
[4184]79char   * print_type_node          = "NODE";
80char   * print_type_transport     = "TRANSPORT";
81char   * print_type_interface     = "IFC";
82char   * print_type_baseband      = "BB";
83char   * print_type_trigger       = "TRIG";
84char   * print_type_user          = "USER";
85
86
87void wl_print_header(u8 level, char * type, char* filename, u32 line) {
88    char * basename = NULL;
89
[4668]90    if (type != NULL) {
91        xil_printf("%s", type);
[4184]92
[4668]93        if ((level <= WL_PRINT_WARNING) || (wl_print_level == WL_PRINT_DEBUG)) {
[4184]94            basename =  strrchr(filename, '/') ? strrchr(filename, '/') + 1 : filename;
[4668]95        }
[4184]96
[4668]97        if (wl_print_level == WL_PRINT_DEBUG) {
98            xil_printf(" (%s:%d): ", basename, line);
99        } else {
100            xil_printf(": ");
101        }
[4184]102
[4668]103        switch(level) {
104            case WL_PRINT_ERROR:
105                xil_printf("ERROR (%s:%d): ", basename, line);
106                increment_red_leds_one_hot();
107            break;
[4184]108
[4668]109            case WL_PRINT_WARNING:
110                xil_printf("WARNING (%s:%d): ", basename, line);
111            break;
112        }
113    }
[4184]114}
[1915]115
116
[4184]117void wl_print_mac_address(u8 level, u8 * mac_address) {
118    u32 i;
[1915]119
[4184]120    if (level <= wl_print_level) {
[4668]121        xil_printf("%02x", mac_address[0]);
[1915]122
[4668]123        for ( i = 1; i < ETH_ADDR_LEN; i++ ) {
124            xil_printf(":%02x", mac_address[i]);
125        }
[4184]126    }
[1915]127}
128
[4184]129
130void wl_set_print_level(u8 level) {
131
[4668]132    switch(level) {
[4184]133        case WL_PRINT_NONE:
134        case WL_PRINT_ERROR:
135        case WL_PRINT_WARNING:
136        case WL_PRINT_INFO:
137        case WL_PRINT_DEBUG:
[4668]138            wl_print_level = level;
[4184]139        break;
140
141        default:
[4668]142            xil_printf("Unsupported print level.  Setting to WLAN_EXP_PRINT_ERROR.\n");
143            wl_print_level = WL_PRINT_ERROR;
[4184]144        break;
[4668]145    }
[2013]146}
147
[1915]148
149
[4453]150/*****************************************************************************
151 *
152 * Hardware initialization functions
153 *
154 *****************************************************************************/
[4184]155
[4453]156/********************************************************************
[4184]157 * @brief Timer Initialization
158 *
159 * @param  None
[4668]160 *
161 * @return  int              - Status of the command:
162 *                                 XST_SUCCESS             - Initialization was successful
163 *                                 XST_DEVICE_IS_STARTED   - The device has already been started
164 *                                 XST_DEVICE_NOT_FOUND    - The device doesn't exist
165 *
[4453]166 ********************************************************************/
[2013]167int wl_timer_initialize(){
[4668]168    int             status            = XST_SUCCESS;
169    XTmrCtr        *TmrCtrInstancePtr = &TimerCounter;
170    XTmrCtr_Config *TmrCtrConfigPtr;
[2013]171
[4668]172    // Initialize the timer counter
173    status = XTmrCtr_Initialize(TmrCtrInstancePtr, TMRCTR_DEVICE_ID);
[4184]174
[4668]175    if (status == XST_DEVICE_IS_STARTED) {
176        wl_printf(WL_PRINT_INFO, print_type_node, "Timer was already running; clear/init manually\n");
[4184]177
[4668]178        TmrCtrConfigPtr = XTmrCtr_LookupConfig(TMRCTR_DEVICE_ID);
[4184]179
[4668]180        TmrCtrInstancePtr->BaseAddress = TmrCtrConfigPtr->BaseAddress;
181        TmrCtrInstancePtr->IsReady     = XIL_COMPONENT_IS_READY;
[4184]182
[4668]183        XTmrCtr_Stop(TmrCtrInstancePtr, 0);
184        XTmrCtr_Reset(TmrCtrInstancePtr, 0);
[4184]185
[4668]186        status = XTmrCtr_Initialize(TmrCtrInstancePtr, TMRCTR_DEVICE_ID);
187    }
[4184]188
[4668]189    if (status != XST_SUCCESS) {
190        wl_printf(WL_PRINT_ERROR, print_type_node, "XtmrCtr_Initialize failed with status %d\n", status);
191    }
[2013]192
[4668]193    // Set timer 0 to into a "count down" mode
194    XTmrCtr_SetOptions(TmrCtrInstancePtr, 0, (XTC_DOWN_COUNT_OPTION));
195    XTmrCtr_SetResetValue(TmrCtrInstancePtr, 1, 0);                       // Sets timer so issuing a "start" command begins at counter = 0
[2013]196
[4668]197    return status;
[4184]198}
[2013]199
200
[4184]201
[4453]202/*****************************************************************************
203 *
204 * Common functions
205 *
206 *****************************************************************************/
207
208/********************************************************************
209 * Node Null Callbacks
210 *
211 * This function is part of the callback system for processing node commands.
212 * If there are no additional node commands, then this will return appropriate values.
213 *
[4668]214 * @param   void * param     - Parameters for the callback
215 *
216 * @return  int              - Status of the command:
217 *                                 XST_SUCCESS  - Command successful
218 *
[4453]219 ********************************************************************/
220int wl_null_callback(void* param){
[4668]221    wl_printf(WL_PRINT_INFO, print_type_node, "WL NULL callback\n");
222    return XST_SUCCESS;
[4453]223}
224
225
226
227/********************************************************************
228 * @brief Set/Clear debug GPIO pins
229 *
[4668]230 * @param   mask             - u8 Bit mask to set / clear GPIO pins on the debug header
231 *
232 * @return  None
233 *
[4453]234 ********************************************************************/
235inline void wl_setDebugGPIO(u8 mask){
[4668]236    XGpio_DiscreteSet(&GPIO_debugpin, 1, mask);
[4453]237}
238
239inline void wl_clearDebugGPIO(u8 mask){
[4668]240    XGpio_DiscreteClear(&GPIO_debugpin, 1, mask);
[4453]241}
242
243
244
245/********************************************************************
246 * @brief Mapping of hexadecimal values to the 7-segment display
247 *
[4668]248 * @param   hex_value        - u8 Hexadecimal value to be converted (between 0 and 15)
249 *
250 * @return  u8               - LED map value of the 7-segment display
251 *
[4453]252 ********************************************************************/
253u8   sevenSegmentMap(u8 hex_value) {
254    switch(hex_value) {
255        case(0x0) : return 0x3F;
256        case(0x1) : return 0x06;
257        case(0x2) : return 0x5B;
258        case(0x3) : return 0x4F;
259        case(0x4) : return 0x66;
260        case(0x5) : return 0x6D;
261        case(0x6) : return 0x7D;
262        case(0x7) : return 0x07;
263        case(0x8) : return 0x7F;
264        case(0x9) : return 0x6F;
265
266        case(0xA) : return 0x77;
267        case(0xB) : return 0x7C;
268        case(0xC) : return 0x39;
269        case(0xD) : return 0x5E;
270        case(0xE) : return 0x79;
271        case(0xF) : return 0x71;
272        default   : return 0x00;
273    }
274}
275
276
277
278/********************************************************************
279 * @brief Pretty print a buffer of u8
280 *
[4668]281 * @param   buf              - Pointer to u8 buffer to be printed
282 * @param   size             - Number of bytes to be printed
283 *
284 * @return  None
285 *
[4453]286 ********************************************************************/
287void print_array_u8(u8 *buf, u32 size) {
[4668]288    u32 i;
289    for (i = 0; i < size; i++) {
[4453]290        xil_printf("%2x ", buf[i]);
291        if ( (((i + 1) % 16) == 0) && ((i + 1) != size) ) {
292            xil_printf("\n");
293        }
[4668]294    }
295    xil_printf("\n\n");
[4453]296}
297
298
299#if _MEASUREMENT_PRINT_
300/********************************************************************
301 * @brief Pretty print a buffer of u32 formatted for measurement purposes
302 *
[4668]303 * @param   buf              - Pointer to u32 buffer to be printed
304 * @param   size             - Number of u32 words to be printed
305 *
306 * @return  None
307 *
[4453]308 ********************************************************************/
309void print_array_u32(u32 *buf, u32 size) {
[4668]310    u32 i;
311    xil_printf("[");
312    for (i = 0; i < size; i++) {
[4453]313        xil_printf("0x%08x, ", buf[i]);
314        if ( (((i + 1) % _MEASUREMENT_PRINT_WIDTH_ ) == 0) && ((i + 1) != size) ) {
315            xil_printf("],\n[");
316        }
[4668]317    }
318    xil_printf("]\n\n");
[4453]319}
320
321
322#else
323
324
325/********************************************************************
326 * @brief Pretty print a buffer of u32
327 *
[4668]328 * @param   buf              - Pointer to u32 buffer to be printed
329 * @param   size             - Number of u32 words to be printed
330 *
331 * @return  None
332 *
[4453]333 ********************************************************************/
334void print_array_u32(u32 *buf, u32 size) {
[4668]335    u32 i;
336    for (i = 0; i < size; i++) {
[4453]337        xil_printf("0x%08x ", buf[i]);
338        if ( (((i + 1) % 4) == 0) && ((i + 1) != size) ) {
339            xil_printf("\n");
340        }
[4668]341    }
342    xil_printf("\n\n");
[4453]343}
344
345
346#endif
347
348
349/********************************************************************
350 * @brief Get Microsecond Counter Timestamp
351 *
352 * The Reference Design includes a 64-bit counter that increments with
353 * every microsecond. This function returns this value.
354 *
[4668]355 * @param   None
356 *
357 * @return  u64              - Current number of microseconds that have elapsed since the hardware has booted.
358 *
[4453]359 ********************************************************************/
360u64 get_usec_timestamp(){
[4668]361    u32 timestamp_high_u32;
362    u32 timestamp_low_u32;
363    u64 timestamp_u64;
[4453]364
[4668]365    timestamp_high_u32 = wl_get_timer_64_MSB();
366    timestamp_low_u32  = wl_get_timer_64_LSB();
[4453]367
[4668]368    // Catch very rare race when 32-LSB of 64-bit value wraps between the two 32-bit reads
369    if( (timestamp_high_u32 & 0x1) != (wl_get_timer_64_MSB() & 0x1) ) {
370        // 32-LSB wrapped - start over
371        timestamp_high_u32 = wl_get_timer_64_MSB();
372        timestamp_low_u32  = wl_get_timer_64_LSB();
373    }
[4453]374
[4668]375    timestamp_u64      = (((u64)timestamp_high_u32) << 32) + ((u64)timestamp_low_u32);
[4453]376
[4668]377    return timestamp_u64;
[4453]378}
379
380
381
382/**********************************************************************************************************************/
[4184]383/**
[4453]384 * @brief WARP v3 Specific Functions
385 *
386 **********************************************************************************************************************/
387
388#ifdef WARP_HW_VER_v3
389
390/***************************** Include Files *********************************/
391
392#include "stdlib.h"
393#include "ctype.h"
394#include "stdarg.h"
395
396#include <xil_exception.h>
397
398#include <xintc.h>
399#include <xaxicdma.h>
400#include <xuartlite.h>
401
402#ifdef XPAR_XSYSMON_NUM_INSTANCES
[4668]403    #include <xsysmon_hw.h>
[4453]404#endif
405
406
407/*************************** Constant Definitions ****************************/
408
409// Peripheral defines
410#define DEBUG_GPIO_DEVICE_ID                               XPAR_AXI_GPIO_0_DEVICE_ID
411#define CDMA_DEVICE_ID                                     XPAR_AXI_CDMA_0_DEVICE_ID
412#define UARTLITE_DEVICE_ID                                 XPAR_UARTLITE_0_DEVICE_ID
413#define INTC_DEVICE_ID                                     XPAR_INTC_0_DEVICE_ID
414
415// UART defines
416#define UARTLITE_INTERRUPT_ID                              XPAR_INTC_0_UARTLITE_0_VEC_ID
417#define UART_BUFFER_SIZE                                   1                                 ///< UART is configured to read 1 byte at a time
418
419// CDMA defines
420#define CDMA_ALIGNMENT                                     0x10
421#define CDMA_ALIGNMENT_MASK                                0xFFFFFFF0
422
423
424/*********************** Global Variable Definitions *************************/
425
426/*************************** Variable Definitions ****************************/
427
428// Peripherals
429XAxiCdma                          cdma_inst;                    ///< Instance of the CDMA device
430static XIntc                      InterruptController;          ///< Interrupt Controller instance
431static XUartLite                  UartLite;                     ///< UART Device instance
432
433// UART interface
434u8                                uart_rx_buffer[UART_BUFFER_SIZE];  ///< Buffer for received byte from UART
435volatile wl_function_ptr_t        uart_callback;                     ///< User callback for UART reception
436
437// Interrupt State
438volatile static interrupt_state_t interrupt_state;
439
440
441/*************************** Functions Prototypes ****************************/
442
443void wl_uart_rx_handler(void* CallBackRef, unsigned int EventData);
444
445
446
447/******************************** Functions **********************************/
448
449
450/********************************************************************
[4184]451 * @brief Debug GPIO Initialization
452 *
453 * @param  None
[4668]454 *
[4184]455 * @return None
[4668]456 *
[4453]457 ********************************************************************/
[4184]458void wl_gpio_debug_initialize(){
[4668]459    XGpio_Initialize(&GPIO_debugpin, DEBUG_GPIO_DEVICE_ID);
460    XGpio_DiscreteClear(&GPIO_debugpin, 1, 0xFF);
[1915]461}
462
[4184]463
[4453]464/********************************************************************
[4196]465 * @brief System Monitor Initialization
[4184]466 *
[4196]467 * @param  None
[4668]468 *
[4184]469 * @return None
[4668]470 *
[4453]471 ********************************************************************/
[4196]472void wl_sysmon_initialize(){
473
474#ifdef XPAR_XSYSMON_NUM_INSTANCES
[4668]475    u32 RegValue;
[4196]476
[4668]477    // Reset the device.
478    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_SRR_OFFSET, XSM_SRR_IPRST_MASK);
[4196]479
[4668]480    // Disable the Channel Sequencer before configuring the Sequence registers.
481    RegValue = XSysMon_ReadReg(SYSMON_BASEADDR, XSM_CFR1_OFFSET) & (~ XSM_CFR1_SEQ_VALID_MASK);
482    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_CFR1_OFFSET,    RegValue | XSM_CFR1_SEQ_SINGCHAN_MASK);
[4196]483
[4668]484    // Setup the Averaging to be done for the channels in the Configuration 0 register as 16 samples
485    RegValue = XSysMon_ReadReg(SYSMON_BASEADDR, XSM_CFR0_OFFSET) & (~XSM_CFR0_AVG_VALID_MASK);
486    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_CFR0_OFFSET, RegValue | XSM_CFR0_AVG16_MASK);
[4196]487
[4668]488    // Enable the averaging on the following channels in the Sequencer registers:
489    //   - On-chip Temperature
490    //   - On-chip VCCAUX supply sensor
491    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_SEQ02_OFFSET, XSM_SEQ_CH_TEMP | XSM_SEQ_CH_VCCAUX);
[4196]492
[4668]493    // Enable the following channels in the Sequencer registers:
494    //   - On-chip Temperature
495    //   - On-chip VCCAUX supply sensor
496    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_SEQ00_OFFSET, XSM_SEQ_CH_TEMP | XSM_SEQ_CH_VCCAUX);
[4196]497
[4668]498    // Set the ADCCLK frequency equal to 1/32 of System clock for the System
499    // Monitor/ADC in the Configuration Register 2.
500    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_CFR2_OFFSET, 32 << XSM_CFR2_CD_SHIFT);
[4196]501
[4668]502    // Enable the Channel Sequencer in continuous sequencer cycling mode.
503    RegValue = XSysMon_ReadReg(SYSMON_BASEADDR, XSM_CFR1_OFFSET) & (~ XSM_CFR1_SEQ_VALID_MASK);
504    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_CFR1_OFFSET,    RegValue | XSM_CFR1_SEQ_CONTINPASS_MASK);
[4196]505
[4668]506    // Wait till the End of Sequence occurs
507    XSysMon_ReadReg(SYSMON_BASEADDR, XSM_SR_OFFSET); /* Clear the old status */
508    while (((XSysMon_ReadReg(SYSMON_BASEADDR, XSM_SR_OFFSET)) &
509            XSM_SR_EOS_MASK) != XSM_SR_EOS_MASK);
[4196]510
511#endif
512
[4184]513}
514
[4196]515
[4453]516/********************************************************************
[4196]517 * @brief Central DMA Initialization
518 *
519 * @param  None
[4668]520 *
521 * @return  int              - Status of the command:
522 *                                 XST_SUCCESS             - Initialization was successful
523 *                                 XST_DEVICE_IS_STARTED   - The device has already been started
524 *                                 XST_DEVICE_NOT_FOUND    - The device doesn't exist
525 *
[4453]526 ********************************************************************/
[4196]527int wl_cdma_initialize(){
[4668]528    int              status            = XST_SUCCESS;
529    XAxiCdma_Config *cdma_cfg_ptr;
[4196]530
[4668]531    cdma_cfg_ptr = XAxiCdma_LookupConfig(CDMA_DEVICE_ID);
[4196]532
[4668]533    status = XAxiCdma_CfgInitialize(&cdma_inst, cdma_cfg_ptr, cdma_cfg_ptr->BaseAddress);
[4196]534
[4668]535    if (status != XST_SUCCESS) {
536        wl_printf(WL_PRINT_ERROR, print_type_node, "CDMA initialization failed with status: %d\n", status );
537        return XST_FAILURE;
538    }
[4196]539
[4668]540    XAxiCdma_IntrDisable(&cdma_inst, XAXICDMA_XR_IRQ_ALL_MASK);
[4196]541
[4668]542    return status;
[4184]543}
544
545
546
[4453]547/********************************************************************
[4196]548 * @brief UART Initialization
[4184]549 *
[4196]550 * @param  None
[4668]551 *
552 * @return  int              - Status of the command:
553 *                                 XST_SUCCESS             - Initialization was successful
554 *                                 XST_DEVICE_IS_STARTED   - The device has already been started
555 *                                 XST_DEVICE_NOT_FOUND    - The device doesn't exist
556 *
[4453]557 ********************************************************************/
[4196]558int wl_uart_initialize(){
[4668]559    int              status            = XST_SUCCESS;
[4196]560
[4668]561    status = XUartLite_Initialize(&UartLite, UARTLITE_DEVICE_ID);
[4196]562
[4668]563    if (status != XST_SUCCESS) {
564        wl_printf(WL_PRINT_ERROR, print_type_node, "UART initialization failed with status: %d\n", status);
565        return XST_FAILURE;
566    }
[4196]567
[4668]568    uart_callback            = (wl_function_ptr_t)wl_null_callback;
[4284]569
[4668]570    return status;
[4196]571}
572
573
[4453]574/********************************************************************
[4196]575 * @brief Use CDMA to transfer data from source address to destination address
576 *
[4668]577 * @param   src_address      - Source address (u32) of the transfer
578 * @param   dest_address     - Destination address (u32) of the transfer
579 * @param   length           - Length of the transfer in bytes
[4196]580 *
[4668]581 * @return  None
[4234]582 *
583 * @note  The CDMA is 128 bits and contains no data re-alignment engine
584 *   (limitation of the IP).  Therefore, we can only perform 16 byte aligned
[4668]585 *   transfers without issue.  If the transfer was unaligned, we will issue
586 *   a warning since this call can be in timing critical loops.
587 *
588 * @note  This function does not wait for a DMA transfer to complete once it
589 *   has been issued.  This allows the CPU to pipeline instructions while the
590 *   DMA is transferring data.  However, this function will wait for the DMA
591 *   to be ready if it is currently in use.
592 *
[4453]593 ********************************************************************/
[4196]594void wl_cdma_transfer(u32 src_address, u32 dest_address, u32 length){
595
[4668]596    // This code assumes all transfers are 16 byte aligned
[4234]597
[4668]598    // Check if there was an error in the previous transfer and reset the DMA
599    if ( XAxiCdma_GetError(&cdma_inst) != 0x0 ) {
600        wl_printf(WL_PRINT_ERROR, print_type_node, "DMA transfer prior to %d bytes from 0x%08x to 0x%08x failed.\nResetting DMA ... \n\n", length, src_address, dest_address);
601        XAxiCdma_Reset(&cdma_inst);
602        while(!XAxiCdma_ResetIsDone(&cdma_inst)) {}
603    }
[4196]604
[4668]605    // Wait for the DMA to be ready before issuing a new transfer
606    while(XAxiCdma_IsBusy(&cdma_inst)) {}
607    XAxiCdma_SimpleTransfer(&cdma_inst, src_address, dest_address, length, NULL, NULL);
[4196]608
[4668]609    // Issue a warning if the transfer was unaligned
610    if (((src_address  & CDMA_ALIGNMENT_MASK) != src_address ) ||
611        ((dest_address & CDMA_ALIGNMENT_MASK) != dest_address)) {
612        wl_printf(WL_PRINT_ERROR, print_type_node, "DMA transfer not %d byte aligned: %d bytes from 0x%08x to 0x%08x.\n", CDMA_ALIGNMENT, length, src_address, dest_address);
613    }
[1915]614}
615
[4284]616int  wl_cdma_busy() {
[4668]617    return XAxiCdma_IsBusy(&cdma_inst);
[4284]618}
619
620
[4453]621/********************************************************************
[4196]622 * @brief Initialize WARPLab Interrupts
623 *
624 * This function initializes sets up the interrupt subsystem of WARPLab.
625 *
[4668]626 * @param   None
627 *
628 * @return  int              - Status of the command:
629 *                                 XST_SUCCESS             - Initialization was successful
630 *                                 XST_DEVICE_IS_STARTED   - The device has already been started
631 *                                 XST_DEVICE_NOT_FOUND    - The device doesn't exist
632 *                                 XST_FAILURE             - Initialization of an interrupt was not successful
633 *
[4453]634 ********************************************************************/
[4196]635int wl_interrupt_init(){
[4668]636    int Result;
[4196]637
[4668]638    // Set interrupt state
639    interrupt_state = INTERRUPTS_DISABLED;
[4196]640
641
[4668]642    // ***************************************************
643    // Initialize XIntc
644    // ***************************************************
645    Result = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
646    if (Result != XST_SUCCESS) {
647        return Result;
648    }
[4196]649
[4668]650    // ***************************************************
651    // Connect interrupt devices
652    // ***************************************************
653    Result = XIntc_Connect(&InterruptController, UARTLITE_INTERRUPT_ID, (XInterruptHandler)XUartLite_InterruptHandler, &UartLite);
654    if (Result != XST_SUCCESS) {
655        wl_printf(WL_PRINT_ERROR, print_type_node, "Failed to connect XUartLite to XIntc\n");
656        return Result;
657    }
658    XIntc_Enable(&InterruptController, UARTLITE_INTERRUPT_ID);
659    XUartLite_SetRecvHandler(&UartLite, wl_uart_rx_handler, &UartLite);
660    XUartLite_EnableInterrupt(&UartLite);
[4196]661
662
[4668]663    Result = wl_baseband_setup_interrupt(&InterruptController);
664    if (Result != XST_SUCCESS) {
665        wl_printf(WL_PRINT_ERROR, print_type_node, "Failed to set up baseband interrupt\n");
666        return XST_FAILURE;
667    }
[4196]668
[4668]669    // ***************************************************
670    // Enable MicroBlaze exceptions
671    // ***************************************************
672    Xil_ExceptionInit();
673    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XIntc_InterruptHandler, &InterruptController);
674    Xil_ExceptionEnable();
[4196]675
[4668]676    // Finish setting up any subsystems that were waiting on interrupts to be configured
677    //    - None at this time
[4196]678
[4668]679    return XST_SUCCESS;
[4196]680}
681
682
[4453]683/********************************************************************
[4196]684 * @brief Restore the state of the interrupt controller
685 *
[4668]686 * This function will restore the state of the interrupt controller to the value
687 * specified by the "new_interrupt_state" argument.  This behavior allows this
688 * function to be used with wl_interrupt_stop() to wrap code that is not interrupt
689 * safe and not worry about the current state of the interrupt controller.
[4196]690 *
[4668]691 * @param  new_interrupt_state    - State to return interrupts. Typically, this argument
692 *                                  is the output of a previous call to wl_interrupt_stop()
693 *
694 * @return  int              - Status of the command:
695 *                                 XST_SUCCESS  - Command successful
696 *                                 XST_FAILURE  - Command not successful
697 *
[4453]698 ********************************************************************/
[4196]699inline int wl_interrupt_restore_state(interrupt_state_t new_interrupt_state){
[4668]700    interrupt_state = new_interrupt_state;
[4196]701
[4668]702    // Enable the interrupts based on the new interrupt state
703    if(interrupt_state == INTERRUPTS_ENABLED){
704        if(InterruptController.IsReady && InterruptController.IsStarted == 0){
705            return XIntc_Start(&InterruptController, XIN_REAL_MODE);
706        } else {
707            return XST_FAILURE;
708        }
709    } else {
710        return XST_SUCCESS;
711    }
[4196]712}
713
714
[4453]715/********************************************************************
[4196]716 * @brief Stop the interrupt controller
717 *
[4668]718 * This function stops the interrupt controller, effectively pausing interrupts and returns
719 * the current state of the interrupts (ie whether the interrupts were currently enabled or
720 * disabled).  This can then be used along with wl_interrupt_restore_state() to wrap code
721 * that is not interrupt-safe.
[4196]722 *
[4668]723 * @param   None
[4196]724 *
[4668]725 * @return  interrupt_state_t     - Current state of interrupts (when function was called):
726 *                                    INTERRUPTS_ENABLED   - Interrupts were enabled
727 *                                    INTERRUPTS_DISABLED  - Interrupts were disabled
728 *
[4453]729 * @note Interrupts that occur while the interrupt controller is off will be executed once
730 *   it is turned back on. They will not be "lost" as the interrupt inputs to the controller
731 *   will remain high.
[4668]732 *
[4453]733 ********************************************************************/
[4196]734inline interrupt_state_t wl_interrupt_stop(){
[4668]735    interrupt_state_t curr_state = interrupt_state;        // Save current interrupt state
[4196]736
[4668]737    if(InterruptController.IsReady && InterruptController.IsStarted) XIntc_Stop(&InterruptController);
738    interrupt_state = INTERRUPTS_DISABLED;                 // Set current interrupt state to "Disabled"
[4196]739
[4668]740    return curr_state;
[4196]741}
742
743
[4453]744/********************************************************************
[4196]745 * @brief UART Receive Interrupt Handler
746 *
747 * This function is the interrupt handler for UART receptions. It, in turn,
748 * will execute a callback that the user has previously registered.
749 *
[4668]750 * @param   CallBackRef      - Argument supplied by the XUartLite driver. Unused in this application.
751 * @param   EventData        - Argument supplied by the XUartLite driver. Unused in this application.
752 *
[4196]753 * @return None
754 *
755 * @see wl_set_uart_rx_callback()
[4668]756 *
[4453]757 ********************************************************************/
[4196]758void wl_uart_rx_handler(void* CallBackRef, unsigned int EventData){
[4668]759    XUartLite_Recv(&UartLite, uart_rx_buffer, UART_BUFFER_SIZE);
760    uart_callback(uart_rx_buffer[0]);
[4196]761}
762
763
[4453]764/********************************************************************
[4284]765 * @brief Set UART Reception Callback
766 *
[4668]767 * Tells the framework which function should be called when a byte is received from UART.
[4284]768 *
[4668]769 * @param   callback         - Pointer to callback function
770 *
771 * @return  None
772 *
[4453]773 ********************************************************************/
[4284]774void wl_set_uart_rx_callback(wl_function_ptr_t callback){
[4668]775    uart_callback = callback;
[4284]776}
777
[4196]778
[4453]779/********************************************************************
[4437]780 * @brief Microsecond sleep counter
781 *
[4668]782 * @param   duration         - Duration in microseconds to sleep
783 *
[4437]784 * @return None
[4453]785 *
[4437]786 * @note   For WARP v3, you cannot use usleep until wl_timer_initialize() has been called
[4668]787 *
[4453]788 ********************************************************************/
[4437]789void usleep(u32 duration){
[4668]790    XTmrCtr    *TmrCtrInstancePtr = &TimerCounter;
791    volatile u8 isExpired         = 0;
[4437]792
[4668]793    XTmrCtr_SetResetValue(TmrCtrInstancePtr, 0, (duration * (TIMER_FREQ/1000000)));
794    XTmrCtr_Start(TmrCtrInstancePtr, 0);
[4437]795
[4668]796    while(isExpired != 1){
797        isExpired = XTmrCtr_IsExpired(TmrCtrInstancePtr, 0);
798    }
[4437]799
[4668]800    XTmrCtr_Reset(TmrCtrInstancePtr, 0);
[4437]801}
802
803
[4453]804/********************************************************************
[4292]805 * @brief Test Right Shift Operator
806 *
807 * This function tests the compiler right shift operator.  This is due to a bug in
808 * the Xilinx 14.7 toolchain when the '-Os' flag is used during compilation.  Please
809 * see:  http://warpproject.org/forums/viewtopic.php?id=2472 for more information.
810 *
[4453]811 * @param  None
[4668]812 *
813 * @return  int              - Status of the command:
814 *                                 XST_SUCCESS  - Command successful
815 *                                 XST_FAILURE  - Command not successful
816 *
[4453]817 ********************************************************************/
[4292]818u32 right_shift_test = 0xFEDCBA98;
819
820int microblaze_right_shift_test() {
821    u8 val_3, val_2, val_1, val_0;
822
823    u32 test_val   = right_shift_test;
824    u8 *test_array = (u8 *)&right_shift_test;
825
826    val_3 = (u8)((test_val & 0xFF000000) >> 24);
827    val_2 = (u8)((test_val & 0x00FF0000) >> 16);
828    val_1 = (u8)((test_val & 0x0000FF00) >>  8);
829    val_0 = (u8)((test_val & 0x000000FF) >>  0);
830
831    if ((val_3 != test_array[3]) || (val_2 != test_array[2]) || (val_1 != test_array[1]) || (val_0 != test_array[0])) {
[4668]832        xil_printf("Right shift operator is not operating correctly in this toolchain.\n");
833        xil_printf("Please use Xilinx 14.4 or an optimization level other than '-Os'\n");
[4292]834        xil_printf("See http://warpproject.org/forums/viewtopic.php?id=2472 for more info.\n");
835        return XST_FAILURE;
836    }
837
[4668]838    return XST_SUCCESS;
[4292]839}
840
841
[4453]842/********************************************************************
[4196]843 * @brief Test DDR3 SODIMM Memory Module
844 *
845 * This function tests the integrity of the DDR3 SODIMM module attached to the hardware
846 * by performing various write and read tests. Note, this function will destroy contents
847 * in DRAM, so it should only be called immediately after booting.
848 *
[4453]849 * @param  None
[4668]850 *
851 * @return  int              - Status of the command:
852 *                                 XST_SUCCESS  - Command successful
853 *                                 XST_FAILURE  - Command not successful
854 *
[4453]855 ********************************************************************/
[4196]856int ddr_sodim_memory_test(){
857    u32            status              = XST_SUCCESS;
858
[4668]859    // Test num_test_points of the DDR evenly over the DDR range
860    u32            num_test_points     = 8;
861    u32            ddr_test_step       = (DDR_SIZE / num_test_points);
[4196]862
[4668]863    // Delay to make sure data is written completely to the DDR
864    u32            readback_delay_usec = 10000;
[4196]865
[4668]866    // Memory variables
867    volatile u8    i,j;
[4196]868
[4668]869    volatile u8    test_u8;
870    volatile u16   test_u16;
871    volatile u32   test_u32;
872    volatile u64   test_u64;
[4196]873
[4668]874    volatile u8    readback_u8;
875    volatile u16   readback_u16;
876    volatile u32   readback_u32;
877    volatile u64   readback_u64;
[4196]878
[4668]879    volatile void* memory_ptr;
[4196]880
[4668]881    for(i = 0; i < num_test_points; i++){
882        memory_ptr = (void*)((u8*)DRAM_BASEADDR + (i*ddr_test_step));
[4196]883
[4668]884        for(j = 0; j < 3; j++){
885            // Test 1 byte offsets to make sure byte enables are all working
886            test_u8  = rand() & 0xFF;
887            test_u16 = rand() & 0xFFFF;
888            test_u32 = rand() & 0xFFFFFFFF;
889            test_u64 = (((u64)rand() & 0xFFFFFFFF) << 32) + ((u64)rand() & 0xFFFFFFFF);
[4196]890
[4668]891            // u8 Test
892            *((u8*)memory_ptr) = test_u8;
893            usleep(readback_delay_usec);
894            readback_u8 = *((u8*)memory_ptr);
[4196]895
[4668]896            if(readback_u8 != test_u8){
897                wl_printf(WL_PRINT_ERROR, print_type_node, "0x%08x: %02x != %02x\n", memory_ptr, readback_u8, test_u8);
898                wl_printf(WL_PRINT_ERROR, print_type_node, "DRAM Failure: Addr: 0x%08x -- Unable to verify write of u8\n", memory_ptr);
899                return XST_FAILURE;
900            }
[4196]901
[4668]902            // u16 Test
903            *((u16*)memory_ptr) = test_u16;
904            usleep(readback_delay_usec);
905            readback_u16 = *((u16*)memory_ptr);
[4196]906
[4668]907            if(readback_u16 != test_u16){
908                wl_printf(WL_PRINT_ERROR, print_type_node, "0x%08x: %04x != %04x\n", memory_ptr, readback_u16, test_u16);
909                wl_printf(WL_PRINT_ERROR, print_type_node, "DRAM Failure: Addr: 0x%08x -- Unable to verify write of u16\n", memory_ptr);
910                return XST_FAILURE;
911            }
[4196]912
[4668]913            // u32 Test
914            *((u32*)memory_ptr) = test_u32;
915            usleep(readback_delay_usec);
916            readback_u32 = *((u32*)memory_ptr);
[4196]917
[4668]918            if(readback_u32 != test_u32){
919                wl_printf(WL_PRINT_ERROR, print_type_node, "0x%08x: %08x != %08x\n", memory_ptr, readback_u32, test_u32);
920                wl_printf(WL_PRINT_ERROR, print_type_node, "DRAM Failure: Addr: 0x%08x -- Unable to verify write of u32\n", memory_ptr);
921                return XST_FAILURE;
922            }
[4196]923
[4668]924            // u64 Test
925            *((u64*)memory_ptr) = test_u64;
926            usleep(readback_delay_usec);
927            readback_u64 = *((u64*)memory_ptr);
[4196]928
[4668]929            if(readback_u64 != test_u64){
930                wl_printf(WL_PRINT_ERROR, print_type_node, "0x%08x: %08x%08x != %08x%08x\n", memory_ptr,
931                                                               (u32)(readback_u64 >> 32), (u32)readback_u64, (u32)(test_u64 >> 32), (u32)test_u64);
932                wl_printf(WL_PRINT_ERROR, print_type_node, "DRAM Failure: Addr: 0x%08x -- Unable to verify write of u64\n", memory_ptr);
933                return XST_FAILURE;
934            }
[4196]935
[4668]936            memory_ptr++;
937        }
938    }
[4196]939
[4668]940    return status;
[4196]941}
942
[4387]943
[4453]944/********************************************************************
[4387]945 * @brief Clear DDR3 SODIMM Memory Module
946 *
947 * This function will clear the contents of the DDR
948 *
[4668]949 * @param  verbose           - Print information on time to clear the DDR
950 *
[4387]951 * @return None
[4668]952 *
[4453]953 ********************************************************************/
[4387]954void clear_ddr(u32 verbose) {
[4668]955    u32 i;
956    u64 num_step;
957    u64 step_size;
[4387]958
[4668]959    u64 start_time;
960    u64 end_time;
961    u32 processing_time;
[4387]962
[4668]963    u32 start_address = DRAM_BASEADDR;
964    u64 size          = DDR_SIZE;
[4387]965
[4668]966    start_time = get_usec_timestamp();
[4387]967
968#if 0
[4668]969    // Implementation 1:
970    //     Use CPU to bzero the entire DDR  (approx 84769092 usec)
971    bzero((void *)start_address, size);
[4196]972#endif
973
[4453]974#if 1
[4387]975    // Implementation 2:
[4668]976    //     Use CPU to bzero the first block of DDR
977    //     Use the DMA to zero out the rest of the DDR
978    //
979    // For num_step (all times approx):
980    //     2^10  --> 1149215 usec
981    //     2^11  --> 1107146 usec
982    //     2^12  --> 1089062 usec
983    //     2^13  --> 1082326 usec
984    //     2^14  --> 1080768 usec  <-- Minimum
985    //     2^15  --> 1093902 usec
986    //     2^16  --> 1150738 usec
987    //     2^17  --> 1265897 usec
988    //
989    num_step  = 1 << 14;
990    step_size = size / num_step;
[4196]991
[4668]992    bzero((void *)start_address, step_size);
[4196]993
[4668]994    for (i = 1; i < num_step; i++) {
995        wl_cdma_transfer(start_address, (start_address + (step_size * i)), step_size);
996    }
[4453]997#endif
[4387]998
[4668]999    end_time   = get_usec_timestamp();
1000    processing_time = (end_time - start_time) & 0xFFFFFFFF;
[4387]1001
[4668]1002    if (verbose == WL_VERBOSE) {
1003        wl_printf(WL_PRINT_NONE, NULL, "  Contents cleared in %d (usec)\n", processing_time);
1004    }
[4387]1005}
1006
1007#endif
1008
1009
1010
[4453]1011/**********************************************************************************************************************/
[4292]1012/**
[4453]1013 * @brief Debug Functions
1014 *
1015 **********************************************************************************************************************/
1016
1017
1018/*****************************************************************************
1019 *
1020 * Non-Invasive Debug functions
1021 *
1022 *****************************************************************************/
1023
1024/********************************************************************
[4292]1025 * @brief Add value to debug storage
1026 *
[4668]1027 * @param   value            - Value (u32) to add to debug storage
1028 * @param   enable           - Should the value be added to the debug storage
1029 *
1030 * @return  None
1031 *
[4453]1032 ********************************************************************/
[4292]1033void add_to_debug_storage(u32 value, u32 enable) {
1034#if _DEBUG_STORAGE_
[4668]1035    if ((enable) && (storage_index < _DEBUG_STORAGE_SIZE_)) {
1036        debug_storage[storage_index++] = value;
1037    }
[4292]1038#endif
1039}
1040
1041
[4453]1042/********************************************************************
[4292]1043 * @brief Remove elements from the debug storage
1044 *
[4668]1045 * @param   num_elements     - Number of elements to remove from debug storage
1046 *
1047 * @return  None
1048 *
[4453]1049 ********************************************************************/
[4333]1050void remove_from_debug_storage(u32 num_elements, u32 enable) {
[4292]1051#if _DEBUG_STORAGE_
[4668]1052    if (enable) {
1053        if (num_elements > storage_index) {
1054            storage_index = 0;
1055        } else {
1056            storage_index -= num_elements;
1057        }
1058    }
[4292]1059#endif
1060}
1061
1062
[4453]1063/********************************************************************
[4292]1064 * @brief Reset the debug storage
1065 *
1066 * @param  None
[4668]1067 *
[4292]1068 * @return None
[4668]1069 *
[4453]1070 ********************************************************************/
[4292]1071void reset_debug_storage() {
1072#if _DEBUG_STORAGE_
[4668]1073    storage_index = 0;
1074    wl_printf(WL_PRINT_NONE, NULL, "Cleared Debug Storage.\n");
[4292]1075#endif
1076}
1077
1078
[4453]1079/********************************************************************
[4292]1080 * @brief Print the debug storage
1081 *
[4453]1082 * @param  None
[4668]1083 *
[4292]1084 * @return None
[4668]1085 *
[4453]1086 ********************************************************************/
[4292]1087void print_debug_storage() {
1088#if _DEBUG_STORAGE_
[4668]1089    print_array_u32(debug_storage, storage_index);
[4292]1090#else
[4668]1091    wl_printf(WL_PRINT_NONE, NULL, "Debug storage not enabled.\n");
[4292]1092#endif
1093}
1094
1095
Note: See TracBrowser for help on using the repository browser.