]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c
Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / freedom-metal / src / drivers / sifive_trace.c
1 /* Copyright 2019 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #include <metal/machine/platform.h>
5
6 #ifdef METAL_SIFIVE_TRACE
7
8 #include <metal/drivers/sifive_trace.h>
9 #include <metal/machine.h>
10
11 #define TRACE_REG(offset) (((unsigned long)base + (offset)))
12 #define TRACE_REG8(offset)                                                     \
13     (__METAL_ACCESS_ONCE((__metal_io_u8 *)TRACE_REG(offset)))
14 #define TRACE_REG16(offset)                                                    \
15     (__METAL_ACCESS_ONCE((__metal_io_u16 *)TRACE_REG(offset)))
16 #define TRACE_REG32(offset)                                                    \
17     (__METAL_ACCESS_ONCE((__metal_io_u32 *)TRACE_REG(offset)))
18
19 static void write_itc_uint32(struct metal_uart *trace, uint32_t data) {
20     long base = __metal_driver_sifive_trace_base(trace);
21
22     TRACE_REG32(METAL_SIFIVE_TRACE_ITCSTIMULUS) = data;
23 }
24
25 static void write_itc_uint16(struct metal_uart *trace, uint16_t data) {
26     long base = __metal_driver_sifive_trace_base(trace);
27
28     TRACE_REG16(METAL_SIFIVE_TRACE_ITCSTIMULUS + 2) = data;
29 }
30
31 static void write_itc_uint8(struct metal_uart *trace, uint8_t data) {
32     long base = __metal_driver_sifive_trace_base(trace);
33
34     TRACE_REG8(METAL_SIFIVE_TRACE_ITCSTIMULUS + 3) = data;
35 }
36
37 int __metal_driver_sifive_trace_putc(struct metal_uart *trace,
38                                      unsigned char c) {
39     static uint32_t buffer = 0;
40     static int bytes_in_buffer = 0;
41
42     buffer |= (((uint32_t)c) << (bytes_in_buffer * 8));
43
44     bytes_in_buffer += 1;
45
46     if (bytes_in_buffer >= 4) {
47         write_itc_uint32(trace, buffer);
48
49         buffer = 0;
50         bytes_in_buffer = 0;
51     } else if ((c == '\n') || (c == '\r')) { // partial write
52         switch (bytes_in_buffer) {
53         case 3: // do a full word write
54             write_itc_uint16(trace, (uint16_t)(buffer));
55             write_itc_uint8(trace, (uint8_t)(buffer >> 16));
56             break;
57         case 2: // do a 16 bit write
58             write_itc_uint16(trace, (uint16_t)buffer);
59             break;
60         case 1: // do a 1 byte write
61             write_itc_uint8(trace, (uint8_t)buffer);
62             break;
63         }
64
65         buffer = 0;
66         bytes_in_buffer = 0;
67     }
68
69     return (int)c;
70 }
71
72 void __metal_driver_sifive_trace_init(struct metal_uart *trace, int baud_rate) {
73     // The only init we do here is to make sure ITC 0 is enabled. It is up to
74     // Freedom Studio or other mechanisms to make sure tracing is enabled. If we
75     // try to enable tracing here, it will likely conflict with Freedom Studio,
76     // and they will just fight with each other.
77
78     long base = __metal_driver_sifive_trace_base(trace);
79
80     TRACE_REG32(METAL_SIFIVE_TRACE_ITCTRACEENABLE) |= 0x00000001;
81 }
82
83 __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_trace) = {
84     .uart.init = __metal_driver_sifive_trace_init,
85     .uart.putc = __metal_driver_sifive_trace_putc,
86     .uart.getc = NULL,
87
88     .uart.get_baud_rate = NULL,
89     .uart.set_baud_rate = NULL,
90
91     .uart.controller_interrupt = NULL,
92     .uart.get_interrupt_id = NULL,
93 };
94
95 #endif /* METAL_SIFIVE_TRACE */