| #include <stdint.h> |
| |
| #include <cstring> |
| |
| #include "fpga/add_uint32_m1_bin_header.h" |
| |
| extern "C" int main() { |
| // Copy the embedded binary to Kelvin's ITCM at 0x0. |
| // NB: Use this copy loop instead of memcpy to get word writes |
| // instead of byte writes. |
| uint32_t* itcm_base = |
| reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(0x0)); |
| const uint32_t* add_uint32_m1_bin_u32 = |
| reinterpret_cast<const uint32_t*>(add_uint32_m1_bin); |
| for (unsigned int i = 0; i < add_uint32_m1_bin_len / 4; i++) { |
| *(itcm_base + i) = add_uint32_m1_bin_u32[i]; |
| } |
| |
| // Kelvin run sequence |
| volatile unsigned int *kelvin_reset_csr = |
| reinterpret_cast<volatile unsigned int *>( |
| static_cast<uintptr_t>(0x00030000)); |
| |
| // Release clock gate |
| *kelvin_reset_csr = 1; |
| |
| // Wait one cycle |
| __asm__ volatile("nop"); |
| |
| // Release reset |
| *kelvin_reset_csr = 0; |
| |
| volatile unsigned int *kelvin_status_csr = |
| reinterpret_cast<volatile unsigned int *>( |
| static_cast<uintptr_t>(0x00030008)); |
| // Wait for Kelvin to halt |
| while (!(*kelvin_status_csr & 1)) { |
| for (int i = 0; i < 1000; ++i) { |
| __asm__ volatile("nop"); |
| } |
| } |
| |
| // Configure UART0. |
| // The NCO is calculated as: (baud_rate * 2^20) / clock_frequency |
| // In our case: (115200 * 2^20) / (CLOCK_FREQUENCY_MHZ * 1000000) |
| volatile unsigned int *uart_ctrl = |
| reinterpret_cast<volatile unsigned int *>(0x40000010); |
| const uint64_t uart_ctrl_nco = |
| ((uint64_t)115200 << 20) / (CLOCK_FREQUENCY_MHZ * 1000000); |
| // Enable TX and RX, and set the NCO value. |
| *uart_ctrl = (uart_ctrl_nco << 16) | 3; |
| |
| auto uart_print = [](const char *str) { |
| volatile char *uart_wdata = reinterpret_cast<volatile char *>(0x4000001c); |
| volatile unsigned int *uart_status = |
| reinterpret_cast<volatile unsigned int *>(0x40000014); |
| |
| while (*str) { |
| // Wait until TX FIFO is not full. |
| while (*uart_status & 1) { |
| asm volatile("nop"); |
| } |
| *uart_wdata = *str++; |
| } |
| }; |
| |
| uart_print("Kelvin halted, as expected.\n"); |
| |
| volatile unsigned int *sram = (volatile unsigned int *)0x20000000; |
| *sram = 0xdeadbeef; |
| while (*sram != 0xdeadbeef) { |
| asm volatile("nop"); |
| } |
| |
| return 0; |
| } |