1 /*
2  * Copyright 2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  */
9 
10 #include "fsl_common.h"
11 
12 #include "fsl_component_log.h"
13 
14 #include "fsl_component_log_backend_ringbuffer.h"
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 
20 /* Weak function. */
21 #if defined(__GNUC__)
22 #define __WEAK_FUNC __attribute__((weak))
23 #elif defined(__ICCARM__)
24 #define __WEAK_FUNC __weak
25 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
26 #define __WEAK_FUNC __attribute__((weak))
27 #endif
28 
29 typedef struct log_backend_ring_buffer
30 {
31     uint8_t *ringBuffer;
32     size_t ringBufferLength;
33     size_t ringBufferHead;
34     size_t ringBufferTail;
35     uint8_t initialized;
36 } log_backend_ring_buffer_t;
37 
38 /*******************************************************************************
39  * Prototypes
40  ******************************************************************************/
41 __WEAK_FUNC void log_backend_ringbuffer_update(uint8_t *buffer, size_t head, size_t tail);
log_backend_ringbuffer_update(uint8_t * buffer,size_t head,size_t tail)42 __WEAK_FUNC void log_backend_ringbuffer_update(uint8_t *buffer, size_t head, size_t tail)
43 {
44     (void)buffer;
45     (void)head;
46     (void)tail;
47 }
48 
49 static void log_init_backend_ringbuffer_puts(uint8_t *buffer, size_t length);
50 
51 /*******************************************************************************
52  * Variables
53  ******************************************************************************/
54 
55 static log_backend_ring_buffer_t s_logBackendRingBuffer;
56 
57 LOG_BACKEND_DEFINE(backend_ring_buffer, log_init_backend_ringbuffer_puts);
58 
59 /*******************************************************************************
60  * Code
61  ******************************************************************************/
62 
log_init_backend_ringbuffer_puts(uint8_t * buffer,size_t length)63 static void log_init_backend_ringbuffer_puts(uint8_t *buffer, size_t length)
64 {
65     uint32_t remainingBufferLength;
66     uint32_t copyLength;
67     uint32_t primask;
68 
69     if ((0U == s_logBackendRingBuffer.initialized) || (0U == length))
70     {
71         return;
72     }
73 
74     primask               = DisableGlobalIRQ();
75     remainingBufferLength = (s_logBackendRingBuffer.ringBufferHead + s_logBackendRingBuffer.ringBufferLength -
76                              s_logBackendRingBuffer.ringBufferTail) %
77                             s_logBackendRingBuffer.ringBufferLength;
78     remainingBufferLength = s_logBackendRingBuffer.ringBufferLength - remainingBufferLength - 1U;
79 
80     if (length >= s_logBackendRingBuffer.ringBufferLength)
81     {
82         buffer = &buffer[length - s_logBackendRingBuffer.ringBufferLength + 1U];
83         length = s_logBackendRingBuffer.ringBufferLength - 1U;
84     }
85     copyLength = length;
86 
87     if ((s_logBackendRingBuffer.ringBufferHead + copyLength) > s_logBackendRingBuffer.ringBufferLength)
88     {
89         copyLength = s_logBackendRingBuffer.ringBufferLength - s_logBackendRingBuffer.ringBufferHead;
90     }
91     (void)memcpy(&s_logBackendRingBuffer.ringBuffer[s_logBackendRingBuffer.ringBufferHead], &buffer[0], copyLength);
92     if (copyLength < length)
93     {
94         (void)memcpy(&s_logBackendRingBuffer.ringBuffer[0], &buffer[copyLength], length - copyLength);
95     }
96 
97     if (length >= remainingBufferLength)
98     {
99         s_logBackendRingBuffer.ringBufferHead += length;
100         s_logBackendRingBuffer.ringBufferHead =
101             s_logBackendRingBuffer.ringBufferHead % s_logBackendRingBuffer.ringBufferLength;
102         s_logBackendRingBuffer.ringBufferTail =
103             s_logBackendRingBuffer.ringBufferHead + s_logBackendRingBuffer.ringBufferLength + 1U;
104         s_logBackendRingBuffer.ringBufferTail =
105             s_logBackendRingBuffer.ringBufferTail % s_logBackendRingBuffer.ringBufferLength;
106     }
107     else
108     {
109         s_logBackendRingBuffer.ringBufferHead += length;
110         s_logBackendRingBuffer.ringBufferHead =
111             s_logBackendRingBuffer.ringBufferHead % s_logBackendRingBuffer.ringBufferLength;
112     }
113     EnableGlobalIRQ(primask);
114 
115     log_backend_ringbuffer_update(s_logBackendRingBuffer.ringBuffer, s_logBackendRingBuffer.ringBufferHead,
116                                   s_logBackendRingBuffer.ringBufferTail);
117 }
118 
LOG_InitBackendRingbuffer(log_backend_ring_buffer_config_t * config)119 void LOG_InitBackendRingbuffer(log_backend_ring_buffer_config_t *config)
120 {
121     log_status_t ret;
122     assert((NULL != config) && (NULL != config->ringBuffer) && (0U != config->ringBufferLength));
123 
124     if (0U != s_logBackendRingBuffer.initialized)
125     {
126         return;
127     }
128 
129     (void)memset(&s_logBackendRingBuffer, 0, sizeof(s_logBackendRingBuffer));
130 
131     s_logBackendRingBuffer.ringBuffer       = config->ringBuffer;
132     s_logBackendRingBuffer.ringBufferLength = config->ringBufferLength;
133 
134     ret = LOG_BackendRegister(&backend_ring_buffer);
135     if (kStatus_LOG_Success == ret)
136     {
137         s_logBackendRingBuffer.initialized = 1U;
138     }
139     assert(kStatus_LOG_Success == ret);
140     return;
141 }
142 
LOG_DeinitBackendRingbuffer(void)143 void LOG_DeinitBackendRingbuffer(void)
144 {
145     log_status_t ret;
146 
147     ret = LOG_BackendUnregister(&backend_ring_buffer);
148     if (kStatus_LOG_Success == ret)
149     {
150         s_logBackendRingBuffer.initialized = 0U;
151     }
152     assert(kStatus_LOG_Success == ret);
153     return;
154 }
155