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
Line 
1/** @file wl_common.c
2 *  @brief WARPLab Framework (Common)
3 *
4 *  This contains the code for WARPLab Framework.
5 *
6 *  @copyright Copyright 2013-2015, Mango Communications. All rights reserved.
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 */
13
14
15/**********************************************************************************************************************/
16/**
17 * @brief Common Functions
18 *
19 **********************************************************************************************************************/
20
21
22/***************************** Include Files *********************************/
23
24// Xilinx / Standard library includes
25#include <xparameters.h>
26#include <xil_io.h>
27#include <xio.h>
28
29//#include "stdlib.h"
30//#include "ctype.h"
31#include "string.h"
32//#include "stdarg.h"
33#include "stdio.h"
34
35// Xilinx Peripheral includes
36#include <xtmrctr.h>
37#include <xgpio.h>
38
39// WARPLab includes
40#include "wl_common.h"
41#include "wl_node.h"
42#include "wl_baseband.h"
43
44
45/*************************** Constant Definitions ****************************/
46
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
50
51
52
53/*********************** Global Variable Definitions *************************/
54
55/*************************** Variable Definitions ****************************/
56
57// Peripheral Instances
58static XTmrCtr                    TimerCounter;                 ///< Instance of the Tmrctr device
59static XGpio                      GPIO_debugpin;                ///< Instance of the GPIO device
60
61
62#if _DEBUG_STORAGE_
63u32                debug_storage[_DEBUG_STORAGE_SIZE_];
64u32                storage_index = 0;
65#endif
66
67
68
69/*************************** Functions Prototypes ****************************/
70
71/******************************** Functions **********************************/
72
73/*****************************************************************************
74 *
75 * Debug Printing Functions
76 *
77 *****************************************************************************/
78u8       wl_print_level           = DEFAULT_DEBUG_PRINT_LEVEL;
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
90    if (type != NULL) {
91        xil_printf("%s", type);
92
93        if ((level <= WL_PRINT_WARNING) || (wl_print_level == WL_PRINT_DEBUG)) {
94            basename =  strrchr(filename, '/') ? strrchr(filename, '/') + 1 : filename;
95        }
96
97        if (wl_print_level == WL_PRINT_DEBUG) {
98            xil_printf(" (%s:%d): ", basename, line);
99        } else {
100            xil_printf(": ");
101        }
102
103        switch(level) {
104            case WL_PRINT_ERROR:
105                xil_printf("ERROR (%s:%d): ", basename, line);
106                increment_red_leds_one_hot();
107            break;
108
109            case WL_PRINT_WARNING:
110                xil_printf("WARNING (%s:%d): ", basename, line);
111            break;
112        }
113    }
114}
115
116
117void wl_print_mac_address(u8 level, u8 * mac_address) {
118    u32 i;
119
120    if (level <= wl_print_level) {
121        xil_printf("%02x", mac_address[0]);
122
123        for ( i = 1; i < ETH_ADDR_LEN; i++ ) {
124            xil_printf(":%02x", mac_address[i]);
125        }
126    }
127}
128
129
130void wl_set_print_level(u8 level) {
131
132    switch(level) {
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:
138            wl_print_level = level;
139        break;
140
141        default:
142            xil_printf("Unsupported print level.  Setting to WLAN_EXP_PRINT_ERROR.\n");
143            wl_print_level = WL_PRINT_ERROR;
144        break;
145    }
146}
147
148
149
150/*****************************************************************************
151 *
152 * Hardware initialization functions
153 *
154 *****************************************************************************/
155
156/********************************************************************
157 * @brief Timer Initialization
158 *
159 * @param  None
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 *
166 ********************************************************************/
167int wl_timer_initialize(){
168    int             status            = XST_SUCCESS;
169    XTmrCtr        *TmrCtrInstancePtr = &TimerCounter;
170    XTmrCtr_Config *TmrCtrConfigPtr;
171
172    // Initialize the timer counter
173    status = XTmrCtr_Initialize(TmrCtrInstancePtr, TMRCTR_DEVICE_ID);
174
175    if (status == XST_DEVICE_IS_STARTED) {
176        wl_printf(WL_PRINT_INFO, print_type_node, "Timer was already running; clear/init manually\n");
177
178        TmrCtrConfigPtr = XTmrCtr_LookupConfig(TMRCTR_DEVICE_ID);
179
180        TmrCtrInstancePtr->BaseAddress = TmrCtrConfigPtr->BaseAddress;
181        TmrCtrInstancePtr->IsReady     = XIL_COMPONENT_IS_READY;
182
183        XTmrCtr_Stop(TmrCtrInstancePtr, 0);
184        XTmrCtr_Reset(TmrCtrInstancePtr, 0);
185
186        status = XTmrCtr_Initialize(TmrCtrInstancePtr, TMRCTR_DEVICE_ID);
187    }
188
189    if (status != XST_SUCCESS) {
190        wl_printf(WL_PRINT_ERROR, print_type_node, "XtmrCtr_Initialize failed with status %d\n", status);
191    }
192
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
196
197    return status;
198}
199
200
201
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 *
214 * @param   void * param     - Parameters for the callback
215 *
216 * @return  int              - Status of the command:
217 *                                 XST_SUCCESS  - Command successful
218 *
219 ********************************************************************/
220int wl_null_callback(void* param){
221    wl_printf(WL_PRINT_INFO, print_type_node, "WL NULL callback\n");
222    return XST_SUCCESS;
223}
224
225
226
227/********************************************************************
228 * @brief Set/Clear debug GPIO pins
229 *
230 * @param   mask             - u8 Bit mask to set / clear GPIO pins on the debug header
231 *
232 * @return  None
233 *
234 ********************************************************************/
235inline void wl_setDebugGPIO(u8 mask){
236    XGpio_DiscreteSet(&GPIO_debugpin, 1, mask);
237}
238
239inline void wl_clearDebugGPIO(u8 mask){
240    XGpio_DiscreteClear(&GPIO_debugpin, 1, mask);
241}
242
243
244
245/********************************************************************
246 * @brief Mapping of hexadecimal values to the 7-segment display
247 *
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 *
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 *
281 * @param   buf              - Pointer to u8 buffer to be printed
282 * @param   size             - Number of bytes to be printed
283 *
284 * @return  None
285 *
286 ********************************************************************/
287void print_array_u8(u8 *buf, u32 size) {
288    u32 i;
289    for (i = 0; i < size; i++) {
290        xil_printf("%2x ", buf[i]);
291        if ( (((i + 1) % 16) == 0) && ((i + 1) != size) ) {
292            xil_printf("\n");
293        }
294    }
295    xil_printf("\n\n");
296}
297
298
299#if _MEASUREMENT_PRINT_
300/********************************************************************
301 * @brief Pretty print a buffer of u32 formatted for measurement purposes
302 *
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 *
308 ********************************************************************/
309void print_array_u32(u32 *buf, u32 size) {
310    u32 i;
311    xil_printf("[");
312    for (i = 0; i < size; i++) {
313        xil_printf("0x%08x, ", buf[i]);
314        if ( (((i + 1) % _MEASUREMENT_PRINT_WIDTH_ ) == 0) && ((i + 1) != size) ) {
315            xil_printf("],\n[");
316        }
317    }
318    xil_printf("]\n\n");
319}
320
321
322#else
323
324
325/********************************************************************
326 * @brief Pretty print a buffer of u32
327 *
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 *
333 ********************************************************************/
334void print_array_u32(u32 *buf, u32 size) {
335    u32 i;
336    for (i = 0; i < size; i++) {
337        xil_printf("0x%08x ", buf[i]);
338        if ( (((i + 1) % 4) == 0) && ((i + 1) != size) ) {
339            xil_printf("\n");
340        }
341    }
342    xil_printf("\n\n");
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 *
355 * @param   None
356 *
357 * @return  u64              - Current number of microseconds that have elapsed since the hardware has booted.
358 *
359 ********************************************************************/
360u64 get_usec_timestamp(){
361    u32 timestamp_high_u32;
362    u32 timestamp_low_u32;
363    u64 timestamp_u64;
364
365    timestamp_high_u32 = wl_get_timer_64_MSB();
366    timestamp_low_u32  = wl_get_timer_64_LSB();
367
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    }
374
375    timestamp_u64      = (((u64)timestamp_high_u32) << 32) + ((u64)timestamp_low_u32);
376
377    return timestamp_u64;
378}
379
380
381
382/**********************************************************************************************************************/
383/**
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
403    #include <xsysmon_hw.h>
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/********************************************************************
451 * @brief Debug GPIO Initialization
452 *
453 * @param  None
454 *
455 * @return None
456 *
457 ********************************************************************/
458void wl_gpio_debug_initialize(){
459    XGpio_Initialize(&GPIO_debugpin, DEBUG_GPIO_DEVICE_ID);
460    XGpio_DiscreteClear(&GPIO_debugpin, 1, 0xFF);
461}
462
463
464/********************************************************************
465 * @brief System Monitor Initialization
466 *
467 * @param  None
468 *
469 * @return None
470 *
471 ********************************************************************/
472void wl_sysmon_initialize(){
473
474#ifdef XPAR_XSYSMON_NUM_INSTANCES
475    u32 RegValue;
476
477    // Reset the device.
478    XSysMon_WriteReg(SYSMON_BASEADDR, XSM_SRR_OFFSET, XSM_SRR_IPRST_MASK);
479
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);
483
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);
487
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);
492
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);
497
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);
501
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);
505
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);
510
511#endif
512
513}
514
515
516/********************************************************************
517 * @brief Central DMA Initialization
518 *
519 * @param  None
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 *
526 ********************************************************************/
527int wl_cdma_initialize(){
528    int              status            = XST_SUCCESS;
529    XAxiCdma_Config *cdma_cfg_ptr;
530
531    cdma_cfg_ptr = XAxiCdma_LookupConfig(CDMA_DEVICE_ID);
532
533    status = XAxiCdma_CfgInitialize(&cdma_inst, cdma_cfg_ptr, cdma_cfg_ptr->BaseAddress);
534
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    }
539
540    XAxiCdma_IntrDisable(&cdma_inst, XAXICDMA_XR_IRQ_ALL_MASK);
541
542    return status;
543}
544
545
546
547/********************************************************************
548 * @brief UART Initialization
549 *
550 * @param  None
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 *
557 ********************************************************************/
558int wl_uart_initialize(){
559    int              status            = XST_SUCCESS;
560
561    status = XUartLite_Initialize(&UartLite, UARTLITE_DEVICE_ID);
562
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    }
567
568    uart_callback            = (wl_function_ptr_t)wl_null_callback;
569
570    return status;
571}
572
573
574/********************************************************************
575 * @brief Use CDMA to transfer data from source address to destination address
576 *
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
580 *
581 * @return  None
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
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 *
593 ********************************************************************/
594void wl_cdma_transfer(u32 src_address, u32 dest_address, u32 length){
595
596    // This code assumes all transfers are 16 byte aligned
597
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    }
604
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);
608
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    }
614}
615
616int  wl_cdma_busy() {
617    return XAxiCdma_IsBusy(&cdma_inst);
618}
619
620
621/********************************************************************
622 * @brief Initialize WARPLab Interrupts
623 *
624 * This function initializes sets up the interrupt subsystem of WARPLab.
625 *
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 *
634 ********************************************************************/
635int wl_interrupt_init(){
636    int Result;
637
638    // Set interrupt state
639    interrupt_state = INTERRUPTS_DISABLED;
640
641
642    // ***************************************************
643    // Initialize XIntc
644    // ***************************************************
645    Result = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
646    if (Result != XST_SUCCESS) {
647        return Result;
648    }
649
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);
661
662
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    }
668
669    // ***************************************************
670    // Enable MicroBlaze exceptions
671    // ***************************************************
672    Xil_ExceptionInit();
673    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XIntc_InterruptHandler, &InterruptController);
674    Xil_ExceptionEnable();
675
676    // Finish setting up any subsystems that were waiting on interrupts to be configured
677    //    - None at this time
678
679    return XST_SUCCESS;
680}
681
682
683/********************************************************************
684 * @brief Restore the state of the interrupt controller
685 *
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.
690 *
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 *
698 ********************************************************************/
699inline int wl_interrupt_restore_state(interrupt_state_t new_interrupt_state){
700    interrupt_state = new_interrupt_state;
701
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    }
712}
713
714
715/********************************************************************
716 * @brief Stop the interrupt controller
717 *
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.
722 *
723 * @param   None
724 *
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 *
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.
732 *
733 ********************************************************************/
734inline interrupt_state_t wl_interrupt_stop(){
735    interrupt_state_t curr_state = interrupt_state;        // Save current interrupt state
736
737    if(InterruptController.IsReady && InterruptController.IsStarted) XIntc_Stop(&InterruptController);
738    interrupt_state = INTERRUPTS_DISABLED;                 // Set current interrupt state to "Disabled"
739
740    return curr_state;
741}
742
743
744/********************************************************************
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 *
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 *
753 * @return None
754 *
755 * @see wl_set_uart_rx_callback()
756 *
757 ********************************************************************/
758void wl_uart_rx_handler(void* CallBackRef, unsigned int EventData){
759    XUartLite_Recv(&UartLite, uart_rx_buffer, UART_BUFFER_SIZE);
760    uart_callback(uart_rx_buffer[0]);
761}
762
763
764/********************************************************************
765 * @brief Set UART Reception Callback
766 *
767 * Tells the framework which function should be called when a byte is received from UART.
768 *
769 * @param   callback         - Pointer to callback function
770 *
771 * @return  None
772 *
773 ********************************************************************/
774void wl_set_uart_rx_callback(wl_function_ptr_t callback){
775    uart_callback = callback;
776}
777
778
779/********************************************************************
780 * @brief Microsecond sleep counter
781 *
782 * @param   duration         - Duration in microseconds to sleep
783 *
784 * @return None
785 *
786 * @note   For WARP v3, you cannot use usleep until wl_timer_initialize() has been called
787 *
788 ********************************************************************/
789void usleep(u32 duration){
790    XTmrCtr    *TmrCtrInstancePtr = &TimerCounter;
791    volatile u8 isExpired         = 0;
792
793    XTmrCtr_SetResetValue(TmrCtrInstancePtr, 0, (duration * (TIMER_FREQ/1000000)));
794    XTmrCtr_Start(TmrCtrInstancePtr, 0);
795
796    while(isExpired != 1){
797        isExpired = XTmrCtr_IsExpired(TmrCtrInstancePtr, 0);
798    }
799
800    XTmrCtr_Reset(TmrCtrInstancePtr, 0);
801}
802
803
804/********************************************************************
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 *
811 * @param  None
812 *
813 * @return  int              - Status of the command:
814 *                                 XST_SUCCESS  - Command successful
815 *                                 XST_FAILURE  - Command not successful
816 *
817 ********************************************************************/
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])) {
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");
834        xil_printf("See http://warpproject.org/forums/viewtopic.php?id=2472 for more info.\n");
835        return XST_FAILURE;
836    }
837
838    return XST_SUCCESS;
839}
840
841
842/********************************************************************
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 *
849 * @param  None
850 *
851 * @return  int              - Status of the command:
852 *                                 XST_SUCCESS  - Command successful
853 *                                 XST_FAILURE  - Command not successful
854 *
855 ********************************************************************/
856int ddr_sodim_memory_test(){
857    u32            status              = XST_SUCCESS;
858
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);
862
863    // Delay to make sure data is written completely to the DDR
864    u32            readback_delay_usec = 10000;
865
866    // Memory variables
867    volatile u8    i,j;
868
869    volatile u8    test_u8;
870    volatile u16   test_u16;
871    volatile u32   test_u32;
872    volatile u64   test_u64;
873
874    volatile u8    readback_u8;
875    volatile u16   readback_u16;
876    volatile u32   readback_u32;
877    volatile u64   readback_u64;
878
879    volatile void* memory_ptr;
880
881    for(i = 0; i < num_test_points; i++){
882        memory_ptr = (void*)((u8*)DRAM_BASEADDR + (i*ddr_test_step));
883
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);
890
891            // u8 Test
892            *((u8*)memory_ptr) = test_u8;
893            usleep(readback_delay_usec);
894            readback_u8 = *((u8*)memory_ptr);
895
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            }
901
902            // u16 Test
903            *((u16*)memory_ptr) = test_u16;
904            usleep(readback_delay_usec);
905            readback_u16 = *((u16*)memory_ptr);
906
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            }
912
913            // u32 Test
914            *((u32*)memory_ptr) = test_u32;
915            usleep(readback_delay_usec);
916            readback_u32 = *((u32*)memory_ptr);
917
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            }
923
924            // u64 Test
925            *((u64*)memory_ptr) = test_u64;
926            usleep(readback_delay_usec);
927            readback_u64 = *((u64*)memory_ptr);
928
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            }
935
936            memory_ptr++;
937        }
938    }
939
940    return status;
941}
942
943
944/********************************************************************
945 * @brief Clear DDR3 SODIMM Memory Module
946 *
947 * This function will clear the contents of the DDR
948 *
949 * @param  verbose           - Print information on time to clear the DDR
950 *
951 * @return None
952 *
953 ********************************************************************/
954void clear_ddr(u32 verbose) {
955    u32 i;
956    u64 num_step;
957    u64 step_size;
958
959    u64 start_time;
960    u64 end_time;
961    u32 processing_time;
962
963    u32 start_address = DRAM_BASEADDR;
964    u64 size          = DDR_SIZE;
965
966    start_time = get_usec_timestamp();
967
968#if 0
969    // Implementation 1:
970    //     Use CPU to bzero the entire DDR  (approx 84769092 usec)
971    bzero((void *)start_address, size);
972#endif
973
974#if 1
975    // Implementation 2:
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;
991
992    bzero((void *)start_address, step_size);
993
994    for (i = 1; i < num_step; i++) {
995        wl_cdma_transfer(start_address, (start_address + (step_size * i)), step_size);
996    }
997#endif
998
999    end_time   = get_usec_timestamp();
1000    processing_time = (end_time - start_time) & 0xFFFFFFFF;
1001
1002    if (verbose == WL_VERBOSE) {
1003        wl_printf(WL_PRINT_NONE, NULL, "  Contents cleared in %d (usec)\n", processing_time);
1004    }
1005}
1006
1007#endif
1008
1009
1010
1011/**********************************************************************************************************************/
1012/**
1013 * @brief Debug Functions
1014 *
1015 **********************************************************************************************************************/
1016
1017
1018/*****************************************************************************
1019 *
1020 * Non-Invasive Debug functions
1021 *
1022 *****************************************************************************/
1023
1024/********************************************************************
1025 * @brief Add value to debug storage
1026 *
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 *
1032 ********************************************************************/
1033void add_to_debug_storage(u32 value, u32 enable) {
1034#if _DEBUG_STORAGE_
1035    if ((enable) && (storage_index < _DEBUG_STORAGE_SIZE_)) {
1036        debug_storage[storage_index++] = value;
1037    }
1038#endif
1039}
1040
1041
1042/********************************************************************
1043 * @brief Remove elements from the debug storage
1044 *
1045 * @param   num_elements     - Number of elements to remove from debug storage
1046 *
1047 * @return  None
1048 *
1049 ********************************************************************/
1050void remove_from_debug_storage(u32 num_elements, u32 enable) {
1051#if _DEBUG_STORAGE_
1052    if (enable) {
1053        if (num_elements > storage_index) {
1054            storage_index = 0;
1055        } else {
1056            storage_index -= num_elements;
1057        }
1058    }
1059#endif
1060}
1061
1062
1063/********************************************************************
1064 * @brief Reset the debug storage
1065 *
1066 * @param  None
1067 *
1068 * @return None
1069 *
1070 ********************************************************************/
1071void reset_debug_storage() {
1072#if _DEBUG_STORAGE_
1073    storage_index = 0;
1074    wl_printf(WL_PRINT_NONE, NULL, "Cleared Debug Storage.\n");
1075#endif
1076}
1077
1078
1079/********************************************************************
1080 * @brief Print the debug storage
1081 *
1082 * @param  None
1083 *
1084 * @return None
1085 *
1086 ********************************************************************/
1087void print_debug_storage() {
1088#if _DEBUG_STORAGE_
1089    print_array_u32(debug_storage, storage_index);
1090#else
1091    wl_printf(WL_PRINT_NONE, NULL, "Debug storage not enabled.\n");
1092#endif
1093}
1094
1095
Note: See TracBrowser for help on using the repository browser.