Skip to content

Commit 5bb7bb0

Browse files
nordic-krchrlubos
authored andcommitted
[nrf fromlist] logging: frontend_stmesp: Avoid unaligned word access
write_data function which was writing to STMESP data registers was starting by writing words and tail was written using byte access. However, RISCV core does not support unaligned access and on Cortex-M33 even if supported it is faster to do aligned access. Reworked write_data to start first by writing data using byte or half word access until data pointer is word aligned, then word access is used and finally tail is written using byte or half word access. Upstream PR: zephyrproject-rtos/zephyr#78332 Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 83f64ee commit 5bb7bb0

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

subsys/logging/frontends/log_frontend_stmesp.c

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ BUILD_ASSERT(sizeof(void *) == sizeof(uint32_t));
3333
stmesp_data8(reg, data, timestamp, marked, \
3434
IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_GUARANTEED_ACCESS))
3535

36+
#define STM_D16(reg, data, timestamp, marked) \
37+
stmesp_data16(reg, data, timestamp, marked, \
38+
IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_GUARANTEED_ACCESS))
39+
3640
#define STM_D32(reg, data, timestamp, marked) \
3741
stmesp_data32(reg, data, timestamp, marked, \
3842
IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_GUARANTEED_ACCESS))
@@ -211,18 +215,72 @@ static int early_package_cb(const void *buf, size_t len, void *ctx)
211215

212216
static inline void write_data(const void *data, size_t len, STMESP_Type *const stm_esp)
213217
{
214-
uint32_t *p32 = (uint32_t *)data;
218+
const uint8_t *p8 = data;
219+
const uint32_t *p32;
220+
uint32_t unaligned;
221+
222+
if (!len) {
223+
return;
224+
}
215225

226+
/* Start by writing using D8 or D16 until pointer is word aligned. */
227+
unaligned = (uintptr_t)data & 0x00000003UL;
228+
if (unaligned != 0) {
229+
unaligned = 4 - unaligned;
230+
unaligned = MIN(len, unaligned);
231+
232+
len -= unaligned;
233+
234+
switch (unaligned) {
235+
case 3:
236+
STM_D8(stm_esp, *p8++, false, false);
237+
STM_D16(stm_esp, *(uint16_t *)p8, false, false);
238+
p8 += sizeof(uint16_t);
239+
break;
240+
case 2:
241+
if (len) {
242+
STM_D16(stm_esp, *(uint16_t *)p8, false, false);
243+
p8 += sizeof(uint16_t);
244+
} else {
245+
/* If len 0 then it means that even though 2 bytes are
246+
* to be copied we can have address which is not aligned
247+
* to 2 bytes.
248+
*/
249+
STM_D8(stm_esp, *p8++, false, false);
250+
STM_D8(stm_esp, *p8++, false, false);
251+
}
252+
break;
253+
default:
254+
/* 1 byte to align. */
255+
STM_D8(stm_esp, *p8++, false, false);
256+
}
257+
}
258+
259+
p32 = (const uint32_t *)p8;
260+
261+
/* Use D32 to write as much data as possible. */
216262
while (len >= sizeof(uint32_t)) {
217263
STM_D32(stm_esp, *p32++, false, false);
218264
len -= sizeof(uint32_t);
219265
}
220266

221-
uint8_t *p8 = (uint8_t *)p32;
222-
223-
while (len > 0) {
224-
STM_D8(stm_esp, *p8++, false, false);
225-
len--;
267+
/* Write tail using D16 or D8. Address is word aligned at that point. */
268+
if (len) {
269+
p8 = (const uint8_t *)p32;
270+
switch (len) {
271+
case 2:
272+
STM_D16(stm_esp, *(uint16_t *)p8, false, false);
273+
p8 += sizeof(uint16_t);
274+
break;
275+
case 3:
276+
STM_D16(stm_esp, *(uint16_t *)p8, false, false);
277+
p8 += sizeof(uint16_t);
278+
/* fallthrough */
279+
default:
280+
/* 1 byte to align. */
281+
STM_D8(stm_esp, *p8++, false, false);
282+
break;
283+
}
226284
}
227285
}
228286

0 commit comments

Comments
 (0)