aboutsummaryrefslogtreecommitdiff
path: root/self-test
diff options
context:
space:
mode:
Diffstat (limited to 'self-test')
-rw-r--r--self-test/fmc-test.c240
-rw-r--r--self-test/led-test.c33
-rw-r--r--self-test/short-test.c205
-rw-r--r--self-test/uart-test.c34
4 files changed, 512 insertions, 0 deletions
diff --git a/self-test/fmc-test.c b/self-test/fmc-test.c
new file mode 100644
index 0000000..0e8ff39
--- /dev/null
+++ b/self-test/fmc-test.c
@@ -0,0 +1,240 @@
+//------------------------------------------------------------------------------
+// main.c
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// 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 Novena boot...\r\n");
+
+ // Blink blue LED for six seconds to not upset the Novena at boot.
+ led_on(LED_BLUE);
+ for (i = 0; i < 12; 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, 100000);
+ uart_send_string(", addr: ");
+ uart_send_integer(addr_test_ok, 100000);
+ 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 = 100;
+ } 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;
+ }
+ }
+
+ // 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;
+
+ // we only have 2^22 32-bit words
+ //rnd &= 0x00FFFFFC;
+ rnd &= 0x0007FFFC;
+
+ // 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;
+ }
+ }
+
+ return c;
+}
+
+
+//------------------------------------------------------------------------------
+static void MX_RNG_Init(void)
+//------------------------------------------------------------------------------
+{
+ rng_inst.Instance = RNG;
+ HAL_RNG_Init(&rng_inst);
+}
+
+
+//------------------------------------------------------------------------------
+// EOF
+//------------------------------------------------------------------------------
diff --git a/self-test/led-test.c b/self-test/led-test.c
new file mode 100644
index 0000000..5e4401f
--- /dev/null
+++ b/self-test/led-test.c
@@ -0,0 +1,33 @@
+/*
+ * Blink the four LEDs on the rev01 board in a pattern.
+ */
+#include "stm32f4xx_hal.h"
+#include "stm-init.h"
+#include "stm-led.h"
+
+#define DELAY() HAL_Delay(125)
+
+void toggle_led(uint32_t times, uint32_t led_pin)
+{
+ uint32_t i;
+
+ for (i = 0; i < times; i++) {
+ HAL_GPIO_TogglePin(LED_PORT, led_pin);
+ DELAY();
+ }
+}
+
+int
+main()
+{
+ stm_init();
+
+ while (1)
+ {
+ toggle_led(2, LED_BLUE);
+ toggle_led(2, LED_GREEN);
+ toggle_led(2, LED_YELLOW);
+ toggle_led(2, LED_RED);
+ }
+
+}
diff --git a/self-test/short-test.c b/self-test/short-test.c
new file mode 100644
index 0000000..27b8e7a
--- /dev/null
+++ b/self-test/short-test.c
@@ -0,0 +1,205 @@
+/*
+ * Test code that just sends the letters 'a' to 'z' over and
+ * over again using USART2.
+ *
+ * Toggles the BLUE LED slowly and the RED LED for every
+ * character sent.
+ */
+#include "stm32f4xx_hal.h"
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-uart.h"
+
+void test_for_shorts(char port, GPIO_TypeDef* GPIOx, uint16_t GPIO_Test_Pins);
+
+//------------------------------------------------------------------------------
+// Defines
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+/* These are all the pins used by the FMC interface */
+#define GPIOB_PINS (GPIO_PIN_7)
+
+#define GPIOD_PINS (GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 \
+ |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15 \
+ |GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4 \
+ |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7)
+
+#define GPIOE_PINS (GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7 \
+ |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 \
+ |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15)
+
+#define GPIOF_PINS (GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 \
+ |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13 \
+ |GPIO_PIN_14|GPIO_PIN_15)
+
+#define GPIOG_PINS (GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 \
+ |GPIO_PIN_4|GPIO_PIN_5)
+
+#define GPIOH_PINS (GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 \
+ |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15)
+
+#define GPIOI_PINS (GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 \
+ |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_6|GPIO_PIN_7)
+
+int
+main()
+{
+ stm_init();
+
+ // enable gpio clocks
+ __GPIOA_CLK_ENABLE();
+ __GPIOB_CLK_ENABLE();
+ __GPIOD_CLK_ENABLE();
+ __GPIOE_CLK_ENABLE();
+ __GPIOF_CLK_ENABLE();
+ __GPIOG_CLK_ENABLE();
+ __GPIOH_CLK_ENABLE();
+ __GPIOI_CLK_ENABLE();
+
+ while (1) {
+ HAL_GPIO_TogglePin(LED_PORT, LED_GREEN);
+ uart_send_string("\r\n\r\n\r\n\r\n\r\n");
+
+ test_for_shorts('B', GPIOB, GPIOB_PINS);
+ test_for_shorts('D', GPIOD, GPIOD_PINS);
+ test_for_shorts('E', GPIOE, GPIOE_PINS);
+ test_for_shorts('F', GPIOF, GPIOF_PINS);
+ test_for_shorts('G', GPIOG, GPIOG_PINS);
+ test_for_shorts('H', GPIOH, GPIOH_PINS);
+ test_for_shorts('I', GPIOI, GPIOI_PINS);
+ led_toggle(LED_BLUE);
+ HAL_Delay(2000);
+ }
+}
+
+void configure_all_as_input(GPIO_TypeDef* GPIOx, uint16_t GPIO_Test_Pins)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ /* Configure all pins as input. XXX do all pins (0xffff) instead of just GPIO_Test_Pins? */
+ GPIO_InitStruct.Pin = GPIO_Test_Pins;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
+}
+
+uint8_t check_no_input(char port, GPIO_TypeDef* GPIOx, uint16_t GPIO_Test_Pins, char wrote_port, uint16_t wrote_value)
+{
+ uint16_t read;
+
+ /* Read all pins from port at once. XXX check all pins, not just GPIO_Test_Pins? */
+ read = (GPIOx->IDR & GPIO_Test_Pins);
+
+ if (! read) {
+ /* No unexpected pins read as HIGH */
+ return 0;
+ }
+
+ led_on(LED_RED);
+
+ uart_send_string("Wrote ");
+ uart_send_binary(wrote_value, 16);
+
+ uart_send_string(" to port GPIO");
+ uart_send_char(wrote_port);
+
+ uart_send_string(", read ");
+ uart_send_binary(read, 16);
+
+ uart_send_string(" from GPIO");
+ uart_send_char(port);
+
+ uart_send_string("\r\n");
+
+ return 1;
+}
+
+void test_for_shorts(char port, GPIO_TypeDef* GPIOx, uint16_t GPIO_Test_Pins)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ uint16_t i, fail = 0, Test_Pin, read;
+
+ configure_all_as_input(GPIOB, GPIOB_PINS);
+ configure_all_as_input(GPIOD, GPIOD_PINS);
+ configure_all_as_input(GPIOE, GPIOE_PINS);
+ configure_all_as_input(GPIOF, GPIOF_PINS);
+ configure_all_as_input(GPIOG, GPIOG_PINS);
+ configure_all_as_input(GPIOH, GPIOH_PINS);
+ configure_all_as_input(GPIOI, GPIOI_PINS);
+
+ check_no_input('B', GPIOB, GPIOB_PINS, 'x', 0);
+ check_no_input('D', GPIOD, GPIOD_PINS, 'x', 0);
+ check_no_input('E', GPIOE, GPIOE_PINS, 'x', 0);
+ check_no_input('F', GPIOF, GPIOF_PINS, 'x', 0);
+ check_no_input('G', GPIOG, GPIOG_PINS, 'x', 0);
+ check_no_input('H', GPIOH, GPIOH_PINS, 'x', 0);
+ check_no_input('I', GPIOI, GPIOI_PINS, 'x', 0);
+
+ for (i = 0; i < 31; i++) {
+ Test_Pin = 1 << i;
+ if (! (GPIO_Test_Pins & Test_Pin)) continue;
+
+ configure_all_as_input(GPIOx, GPIO_Test_Pins);
+
+ /* Change one pin to output */
+ GPIO_InitStruct.Pin = Test_Pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
+
+ HAL_GPIO_WritePin(GPIOx, Test_Pin, GPIO_PIN_SET);
+
+ /* Slight delay after setting the output pin. Without this, the Test_Pin
+ bit might read as zero, as it is only sampled once every AHB1 clock cycle.
+ Reference manual DM00031020 section 8.3.1.
+ */
+ HAL_Delay(1);
+
+ /* Read all input GPIOs from port at once. XXX check all pins, not just GPIO_Test_Pins? */
+ read = GPIOx->IDR & GPIO_Test_Pins;
+
+ if (read == Test_Pin) {
+ /* No unexpected pins read as HIGH */
+ led_toggle(LED_GREEN);
+ } else {
+ led_on(LED_RED);
+ uart_send_string("GPIO");
+ uart_send_char(port);
+
+ uart_send_string(" exp ");
+ uart_send_binary(Test_Pin, 16);
+
+ uart_send_string(" got ");
+ uart_send_binary(read, 16);
+
+ uart_send_string(" diff ");
+ uart_send_binary(read ^ Test_Pin, 16);
+
+ uart_send_string("\r\n");
+
+ fail++;
+ }
+
+ /* Check there is no input on any of the other GPIO ports (adjacent pins might live on different ports) */
+ if (port != 'B') fail += check_no_input('B', GPIOB, GPIOB_PINS, port, Test_Pin);
+ if (port != 'D') fail += check_no_input('D', GPIOD, GPIOD_PINS, port, Test_Pin);
+ if (port != 'E') fail += check_no_input('E', GPIOE, GPIOE_PINS, port, Test_Pin);
+ if (port != 'F') fail += check_no_input('F', GPIOF, GPIOF_PINS, port, Test_Pin);
+ if (port != 'G') fail += check_no_input('G', GPIOG, GPIOG_PINS, port, Test_Pin);
+ if (port != 'H') fail += check_no_input('H', GPIOH, GPIOH_PINS, port, Test_Pin);
+ if (port != 'I') fail += check_no_input('I', GPIOI, GPIOI_PINS, port, Test_Pin);
+
+ HAL_GPIO_WritePin(GPIOx, Test_Pin, GPIO_PIN_RESET);
+ }
+
+ if (fail) {
+ uart_send_string("\r\n");
+ }
+}
diff --git a/self-test/uart-test.c b/self-test/uart-test.c
new file mode 100644
index 0000000..8fe7795
--- /dev/null
+++ b/self-test/uart-test.c
@@ -0,0 +1,34 @@
+/*
+ * Test code that just sends the letters 'a' to 'z' over and
+ * over again using USART2.
+ *
+ * Toggles the BLUE LED slowly and the RED LED for every
+ * character sent.
+ */
+#include "stm32f4xx_hal.h"
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-uart.h"
+
+#define DELAY() HAL_Delay(100)
+
+int
+main()
+{
+ uint8_t c = 'a';
+
+ stm_init();
+
+ while (1)
+ {
+ HAL_GPIO_TogglePin(LED_PORT, LED_RED);
+
+ uart_send_char(c);
+ DELAY();
+
+ if (c++ == 'z') {
+ c = 'a';
+ HAL_GPIO_TogglePin(LED_PORT, LED_BLUE);
+ }
+ }
+}