|
| 1 | +// Copyright (c) 2024 Cesanta Software Limited |
| 2 | +// All rights reserved |
| 3 | + |
| 4 | +#include "hal.h" |
| 5 | + |
| 6 | +static volatile uint64_t s_ticks; // Milliseconds since boot |
| 7 | +void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms |
| 8 | + s_ticks++; |
| 9 | +} |
| 10 | + |
| 11 | +void mg_random(void *buf, size_t len) { // Use on-board RNG |
| 12 | + for (size_t n = 0; n < len; n += sizeof(uint32_t)) { |
| 13 | + uint32_t r = rng_read(); |
| 14 | + memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r)); |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +uint64_t mg_millis(void) { // Let Mongoose use our uptime function |
| 19 | + return s_ticks; // Return number of milliseconds since boot |
| 20 | +} |
| 21 | + |
| 22 | +void hal_init(void) { |
| 23 | + clock_init(); // Set system clock to SYS_FREQUENCY |
| 24 | + SystemCoreClock = SYS_FREQUENCY; // Update SystemCoreClock global var |
| 25 | + SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms |
| 26 | + rng_init(); // Initialise random number generator |
| 27 | + |
| 28 | + uart_init(UART_DEBUG, 115200); // Initialise UART |
| 29 | + gpio_output(LED1); // Initialise LED1 |
| 30 | + gpio_output(LED2); // Initialise LED2 |
| 31 | + gpio_output(LED3); // Initialise LED3 |
| 32 | + ethernet_init(); // Initialise Ethernet pins |
| 33 | +} |
| 34 | + |
| 35 | +#if defined(__ARMCC_VERSION) |
| 36 | +// Keil specific - implement IO printf redirection |
| 37 | +int fputc(int c, FILE *stream) { |
| 38 | + if (stream == stdout || stream == stderr) uart_write_byte(UART_DEBUG, c); |
| 39 | + return c; |
| 40 | +} |
| 41 | +#elif defined(__GNUC__) |
| 42 | +// ARM GCC specific. ARM GCC is shipped with Newlib C library. |
| 43 | +// Implement newlib syscalls: |
| 44 | +// _sbrk() for malloc |
| 45 | +// _write() for printf redirection |
| 46 | +// the rest are just stubs |
| 47 | +#include <sys/stat.h> // For _fstat() |
| 48 | + |
| 49 | +uint32_t SystemCoreClock; |
| 50 | +void SystemInit(void) { // Called automatically by startup code |
| 51 | +} |
| 52 | + |
| 53 | +int _fstat(int fd, struct stat *st) { |
| 54 | + (void) fd, (void) st; |
| 55 | + return -1; |
| 56 | +} |
| 57 | + |
| 58 | +extern unsigned char _end[]; // End of data section, start of heap. See link.ld |
| 59 | +static unsigned char *s_current_heap_end = _end; |
| 60 | + |
| 61 | +size_t hal_ram_used(void) { |
| 62 | + return (size_t) (s_current_heap_end - _end); |
| 63 | +} |
| 64 | + |
| 65 | +size_t hal_ram_free(void) { |
| 66 | + unsigned char endofstack; |
| 67 | + return (size_t) (&endofstack - s_current_heap_end); |
| 68 | +} |
| 69 | + |
| 70 | +void *_sbrk(int incr) { |
| 71 | + unsigned char *prev_heap; |
| 72 | + unsigned char *heap_end = (unsigned char *) ((size_t) &heap_end - 256); |
| 73 | + prev_heap = s_current_heap_end; |
| 74 | + // Check how much space we got from the heap end to the stack end |
| 75 | + if (s_current_heap_end + incr > heap_end) return (void *) -1; |
| 76 | + s_current_heap_end += incr; |
| 77 | + return prev_heap; |
| 78 | +} |
| 79 | + |
| 80 | +int _open(const char *path) { |
| 81 | + (void) path; |
| 82 | + return -1; |
| 83 | +} |
| 84 | + |
| 85 | +int _close(int fd) { |
| 86 | + (void) fd; |
| 87 | + return -1; |
| 88 | +} |
| 89 | + |
| 90 | +int _isatty(int fd) { |
| 91 | + (void) fd; |
| 92 | + return 1; |
| 93 | +} |
| 94 | + |
| 95 | +int _lseek(int fd, int ptr, int dir) { |
| 96 | + (void) fd, (void) ptr, (void) dir; |
| 97 | + return 0; |
| 98 | +} |
| 99 | + |
| 100 | +void _exit(int status) { |
| 101 | + (void) status; |
| 102 | + for (;;) asm volatile("BKPT #0"); |
| 103 | +} |
| 104 | + |
| 105 | +void _kill(int pid, int sig) { |
| 106 | + (void) pid, (void) sig; |
| 107 | +} |
| 108 | + |
| 109 | +int _getpid(void) { |
| 110 | + return -1; |
| 111 | +} |
| 112 | + |
| 113 | +int _write(int fd, char *ptr, int len) { |
| 114 | + (void) fd, (void) ptr, (void) len; |
| 115 | + if (fd == 1) uart_write_buf(UART_DEBUG, ptr, (size_t) len); |
| 116 | + return -1; |
| 117 | +} |
| 118 | + |
| 119 | +int _read(int fd, char *ptr, int len) { |
| 120 | + (void) fd, (void) ptr, (void) len; |
| 121 | + return -1; |
| 122 | +} |
| 123 | + |
| 124 | +int _link(const char *a, const char *b) { |
| 125 | + (void) a, (void) b; |
| 126 | + return -1; |
| 127 | +} |
| 128 | + |
| 129 | +int _unlink(const char *a) { |
| 130 | + (void) a; |
| 131 | + return -1; |
| 132 | +} |
| 133 | + |
| 134 | +int _stat(const char *path, struct stat *st) { |
| 135 | + (void) path, (void) st; |
| 136 | + return -1; |
| 137 | +} |
| 138 | + |
| 139 | +int mkdir(const char *path, mode_t mode) { |
| 140 | + (void) path, (void) mode; |
| 141 | + return -1; |
| 142 | +} |
| 143 | + |
| 144 | +void _init(void) { |
| 145 | +} |
| 146 | +#endif // __GNUC__ |
0 commit comments