[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 |
---|
| 58 | static XTmrCtr TimerCounter; ///< Instance of the Tmrctr device |
---|
| 59 | static XGpio GPIO_debugpin; ///< Instance of the GPIO device |
---|
[4184] | 60 | |
---|
| 61 | |
---|
[4292] | 62 | #if _DEBUG_STORAGE_ |
---|
| 63 | u32 debug_storage[_DEBUG_STORAGE_SIZE_]; |
---|
| 64 | u32 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] | 78 | u8 wl_print_level = DEFAULT_DEBUG_PRINT_LEVEL; |
---|
[4184] | 79 | char * print_type_node = "NODE"; |
---|
| 80 | char * print_type_transport = "TRANSPORT"; |
---|
| 81 | char * print_type_interface = "IFC"; |
---|
| 82 | char * print_type_baseband = "BB"; |
---|
| 83 | char * print_type_trigger = "TRIG"; |
---|
| 84 | char * print_type_user = "USER"; |
---|
| 85 | |
---|
| 86 | |
---|
| 87 | void 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] | 117 | void 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 | |
---|
| 130 | void 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] | 167 | int 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 | ********************************************************************/ |
---|
| 220 | int 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 | ********************************************************************/ |
---|
| 235 | inline void wl_setDebugGPIO(u8 mask){ |
---|
[4668] | 236 | XGpio_DiscreteSet(&GPIO_debugpin, 1, mask); |
---|
[4453] | 237 | } |
---|
| 238 | |
---|
| 239 | inline 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 | ********************************************************************/ |
---|
| 253 | u8 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 | ********************************************************************/ |
---|
| 287 | void 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 | ********************************************************************/ |
---|
| 309 | void 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 | ********************************************************************/ |
---|
| 334 | void 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 | ********************************************************************/ |
---|
| 360 | u64 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 |
---|
| 429 | XAxiCdma cdma_inst; ///< Instance of the CDMA device |
---|
| 430 | static XIntc InterruptController; ///< Interrupt Controller instance |
---|
| 431 | static XUartLite UartLite; ///< UART Device instance |
---|
| 432 | |
---|
| 433 | // UART interface |
---|
| 434 | u8 uart_rx_buffer[UART_BUFFER_SIZE]; ///< Buffer for received byte from UART |
---|
| 435 | volatile wl_function_ptr_t uart_callback; ///< User callback for UART reception |
---|
| 436 | |
---|
| 437 | // Interrupt State |
---|
| 438 | volatile static interrupt_state_t interrupt_state; |
---|
| 439 | |
---|
| 440 | |
---|
| 441 | /*************************** Functions Prototypes ****************************/ |
---|
| 442 | |
---|
| 443 | void 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] | 458 | void 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] | 472 | void 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] | 527 | int 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] | 558 | int 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] | 594 | void 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] | 616 | int 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] | 635 | int 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] | 699 | inline 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] | 734 | inline 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] | 758 | void 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] | 774 | void 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] | 789 | void 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] | 818 | u32 right_shift_test = 0xFEDCBA98; |
---|
| 819 | |
---|
| 820 | int 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] | 856 | int 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] | 954 | void 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] | 1033 | void 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] | 1050 | void 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] | 1071 | void 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] | 1087 | void 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 | |
---|