|
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
* stm-uart.h
* ---------
* Functions and defines to use the UART.
*
* Copyright (c) 2015, NORDUnet A/S All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the NORDUnet nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __STM32_UART_H
#define __STM32_UART_H
#include "stm32f4xx_hal.h"
#define USART_MGMT_BAUD_RATE 921600
#define USART_USER_BAUD_RATE 921600
enum stm_uart_port {
STM_UART_USER,
STM_UART_MGMT
};
extern UART_HandleTypeDef huart_mgmt;
extern UART_HandleTypeDef huart_user;
extern HAL_StatusTypeDef uart_send_char(uint8_t ch);
extern HAL_StatusTypeDef uart_recv_char(uint8_t *cp);
extern HAL_StatusTypeDef uart_send_string(char *s);
extern HAL_StatusTypeDef uart_send_number(uint32_t num, uint8_t digits, uint8_t radix);
extern HAL_StatusTypeDef uart_send_char2(enum stm_uart_port port, uint8_t ch);
extern //------------------------------------------------------------------------------
// main.c
//------------------------------------------------------------------------------
/*
This requires a special bitstream with a special test register.
See core/platform/novena/fmc/rtl/novena_fmc_top.v, sections marked
`ifdef test:
//----------------------------------------------------------------
// Dummy Register
//
// General-purpose register to test FMC interface using STM32
// demo program instead of core selector logic.
//
// This register is a bit tricky, but it allows testing of both
// data and address buses. Reading from FPGA will always return
// value, which is currently stored in the test register,
// regardless of read transaction address. Writing to FPGA has
// two variants: a) writing to address 0 will store output data
// data value in the test register, b) writing to any non-zero
// address will store _address_ of write transaction in the test
// register.
//
// To test data bus, write some different patterns to address 0,
// then readback from any address and compare.
//
// To test address bus, write anything to some different non-zero
// addresses, then readback from any address and compare returned
// value with previously written address.
//
//----------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "stm32f4xx_hal.h"
#include "stm-init.h"
#include "stm-led.h"
#include "stm-fmc.h"
#include "stm-uart.h"
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Variables
//------------------------------------------------------------------------------
RNG_HandleTypeDef rng_inst;
// FT: "I changed some interesting-to-look-at-in-the-debugger values to be
// volatile, so that my compiler wouldn't optimize/obscure them."
volatile uint32_t data_diff = 0;
volatile uint32_t addr_diff = 0;
//------------------------------------------------------------------------------
// Prototypes
//------------------------------------------------------------------------------
/* XXX move this to stm-rng.[ch] */
static void MX_RNG_Init(void);
int test_fpga_data_bus(void);
int test_fpga_address_bus(void);
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define TEST_NUM_ROUNDS 100000
//------------------------------------------------------------------------------
int main(void)
//------------------------------------------------------------------------------
{
int i;
stm_init();
uart_send_string("Keep calm for FPGA bitstream loading...\r\n");
// Blink blue LED until the FPGA reports it has loaded it's bitstream
led_on(LED_BLUE);
while (! fpgacfg_check_done()) {
for (i = 0; i < 4; i++) {
HAL_Delay(500);
led_toggle(LED_BLUE);
}
}
// initialize rng
MX_RNG_Init();
// prepare fmc interface
fmc_init();
// turn on green led, turn off other leds
led_on(LED_GREEN);
led_off(LED_YELLOW);
led_off(LED_RED);
led_off(LED_BLUE);
// vars
volatile int data_test_ok = 0, addr_test_ok = 0, successful_runs = 0, failed_runs = 0, sleep = 0;
// main loop (test, until an error is detected)
while (1)
{
// test data bus
data_test_ok = test_fpga_data_bus();
// test address bus
addr_test_ok = test_fpga_address_bus();
uart_send_string("Data: ");
uart_send_integer(data_test_ok, 6);
uart_send_string(", addr: ");
uart_send_integer(addr_test_ok, 6);
uart_send_string("\r\n");
if (data_test_ok == TEST_NUM_ROUNDS &&
addr_test_ok == TEST_NUM_ROUNDS) {
// toggle yellow led to indicate, that we are alive
led_toggle(LED_YELLOW);
successful_runs++;
sleep = 0;
} else {
led_on(LED_RED);
failed_runs++;
sleep = 2000;
}
uart_send_string("Success ");
uart_send_integer(successful_runs, 0);
uart_send_string(", fail ");
uart_send_integer(failed_runs, 0);
uart_send_string("\r\n\r\n");
HAL_Delay(sleep);
}
// should never reach this line
}
//------------------------------------------------------------------------------
int test_fpga_data_bus(void)
//------------------------------------------------------------------------------
{
int c, ok;
uint32_t rnd, buf;
HAL_StatusTypeDef hal_result;
// run some rounds of data bus test
for (c=0; c<TEST_NUM_ROUNDS; c++)
{
data_diff = 0;
// try to generate "random" number
hal_result = HAL_RNG_GenerateRandomNumber(&rng_inst, &rnd);
if (hal_result != HAL_OK) break;
// write value to fpga at address 0
ok = fmc_write_32(0, &rnd);
if (ok != 0) break;
// read value from fpga
ok = fmc_read_32(0, &buf);
if (ok != 0) break;
// compare (abort testing in case of error)
if (buf != rnd)
{
data_diff = buf;
data_diff ^= rnd;
uart_send_string("Data bus fail: expected ");
uart_send_binary(rnd, 32);
uart_send_string(", got ");
uart_send_binary(buf, 32);
uart_send_string(", diff ");
uart_send_binary(data_diff, 32);
uart_send_string("\r\n");
break;
}
}
data_diff = buf;
data_diff ^= rnd;
uart_send_string("Sample of data bus test data: expected ");
uart_send_binary(rnd, 32);
uart_send_string(", got ");
uart_send_binary(buf, 32);
uart_send_string(", diff ");
uart_send_binary(data_diff, 32);
uart_send_string("\r\n");
// return number of successful tests
return c;
}
//------------------------------------------------------------------------------
int test_fpga_address_bus(void)
//------------------------------------------------------------------------------
{
int c, ok;
uint32_t rnd, buf;
HAL_StatusTypeDef hal_result;
// run some rounds of address bus test
for (c=0; c<TEST_NUM_ROUNDS; c++)
{
addr_diff = 0;
// try to generate "random" number
hal_result = HAL_RNG_GenerateRandomNumber(&rng_inst, &rnd);
if (hal_result != HAL_OK) break;
// there are 26 physicaly connected address lines on the alpha,
// but "only" 24 usable for now (the top two ones are used by FMC
// to choose bank, and we only have one bank set up currently)
rnd &= 0x3fffffc;
// don't test zero addresses (fpga will store data, not address)
if (rnd == 0) continue;
// write dummy value to fpga at some non-zero address
ok = fmc_write_32(rnd, &buf);
if (ok != 0) break;
// read value from fpga
ok = fmc_read_32(0, &buf);
if (ok != 0) break;
// fpga receives address of 32-bit word, while we need
// byte address here to compare
buf <<= 2;
// compare (abort testing in case of error)
if (buf != rnd)
{
addr_diff = buf;
addr_diff ^= rnd;
uart_send_string("Addr bus fail: expected ");
uart_send_binary(rnd, 32);
uart_send_string(", got ");
uart_send_binary(buf, 32);
uart_send_string(", diff ");
uart_send_binary(addr_diff, 32);
uart_send_string("\r\n");
break;
}
}
addr_diff = buf;
addr_diff ^= rnd;
uart_send_string("Sample of addr bus test data: expected ");
uart_send_binary(rnd, 32);
uart_send_string(", got ");
uart_send_binary(buf, 32);
uart_send_string(", diff ");
uart_send_binary(addr_diff, 32);
uart_send_string("\r\n");
return c;
}
//------------------------------------------------------------------------------
static void MX_RNG_Init(void)
//------------------------------------------------------------------------------
{
rng_inst.Instance = RNG;
HAL_RNG_Init(&rng_inst);
}
//------------------------------------------------------------------------------
// EOF
//------------------------------------------------------------------------------
|